Ios Swift在离开范围时在CFRelease中崩溃
我刚刚投入到iOS开发中,目前在queryServer函数末尾的函数CFRelease中出现了一个运行时错误(我在get突出显示的行上添加了一条注释),如果我注释掉对extractIPFromQuery的函数调用,则不会出现错误 下面的代码获取服务器的名称并将ip地址列表返回给该服务器Ios Swift在离开范围时在CFRelease中崩溃,ios,swift,Ios,Swift,我刚刚投入到iOS开发中,目前在queryServer函数末尾的函数CFRelease中出现了一个运行时错误(我在get突出显示的行上添加了一条注释),如果我注释掉对extractIPFromQuery的函数调用,则不会出现错误 下面的代码获取服务器的名称并将ip地址列表返回给该服务器 func extractIPFromQuery(query: NSArray) -> [String] { var addresses = [String]() for x in 0...
func extractIPFromQuery(query: NSArray) -> [String] {
var addresses = [String]()
for x in 0...query.count - 1{
let adr = "\(query[x])"
let adrStart = adr.startIndex.advancedBy(10)
let adrEnd = adr.startIndex.advancedBy(18)
let address = adr.substringWithRange(Range<String.Index>(start: adrStart, end: adrEnd))
var final = ""
// Convert the hex version of the address into
// a human readable version
for seg in 0...3{
let start = address.startIndex.advancedBy(seg * 2)
let end = address.startIndex.advancedBy((seg * 2) + 2)
let hexRange = Range<String.Index>(start: start, end: end)
let hexPair = address.substringWithRange(hexRange)
final += "\(UInt8(strtoul(hexPair, nil, 16)))"
if(seg != 3){
final += "."
}
}
addresses.append(final)
}
return addresses;
}
func queryServer(hostName: String) -> [String]{
var ips = [String]()
if hostName != "\0" {
let hostRef = CFHostCreateWithName(kCFAllocatorDefault, hostName).takeRetainedValue()
while(CFHostStartInfoResolution(hostRef, CFHostInfoType.Addresses, nil) == false){}
ips += extractIPFromQuery(CFHostGetAddressing(hostRef, nil)!.takeRetainedValue() as NSArray)
} // Code breaks here
return ips
}
func extractIPFromQuery(查询:NSArray)->[String]{
变量地址=[String]()
对于0中的x…query.count-1{
let adr=“\(查询[x])”
设adrStart=adr.startIndex.advancedBy(10)
设adrEnd=adr.startIndex.预付款(18)
let address=adr.substringWithRange(范围(开始:adrStart,结束:adrEnd))
var final=“”
//将地址的十六进制版本转换为
//可读的版本
对于0…3中的seg{
让start=address.startIndex.advancedBy(seg*2)
让end=address.startIndex.advancedBy((seg*2)+2)
设hexRange=Range(开始:开始,结束:结束)
设hexPair=address.substringWithRange(hexRange)
final+=“\(UInt8(strtoul(六角对,零,16))”
如果(分段!=3){
最终+=“”
}
}
地址。追加(最终)
}
返回地址;
}
func queryServer(主机名:String)->[String]{
变量ips=[String]()
如果主机名!=“\0”{
让hostRef=CFHostCreateWithName(kCFAllocatorDefault,主机名)
while(cfhoststartinefolution(hostRef,CFHostInfoType.Addresses,nil)==false){}
ips+=extractIPFromQuery(CFHostGetAddressing(hostRef,nil)!.takeRetainedValue()作为NSArray)
}//代码在此中断
返回IP
}
CFHostGetAddressing
名称中没有“创建”或“复制”,
这意味着它不会返回(+1)个保留对象。
因此,您必须使用takeUnretainedValue()
来获取
非托管引用的值
有关这些命名约定的更多信息,请参阅“创建规则”和“获取规则”
在里面
在“Core Foundation的内存管理编程指南”中,您获得了
CFHostGetAddressing
返回的数组的所有权,这意味着ARC
将插入一个release
调用来平衡认为需要平衡的retain
调用,而实际上它不需要这样做。您应该使用takeUnrepainedValue()
而不是takeRetainedValue()
,因为CFHostGetAddressing
的名称语义并不意味着您需要获得结果的所有权
在基本层面上,
takeRetainedValue()
和takeUnrepainedValue()
之间的区别在于前者将指示ARC在变量get超出范围时插入release
调用,而后者则不会。在语义层面上,前一个表示您想要或需要获得变量的所有权,通常意味着对该对象有一个不平衡的retain
调用,哪个ARC
将保持平衡。在调用queryServer
时是否传递有效的服务器名称?该代码确实有效,并且ips中填充了一组地址,因为离开if
范围时会崩溃,这意味着它与作用域中使用的变量之一有关:hostRef
或CFHostGetAddressing
的结果。还可以使用getnameinfo()
查看一种更简单的方法,将IP地址转换为字符串。谢谢您和@Cristik,它们解决了我的问题。