离开范围时,Swift在CFRelease中崩溃

我刚刚投入到iOS开发中,我目前在查询服务器函数结束时在函数CFRelease中收到运行时错误(我对突出显示的行放置注释)并且我没有错误如果我注释掉函数调用extractIPFromQuery。

下面的代码是服务器的名称,并返回该服务器的IP地址列表。

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(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(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 } 

CFHostGetAddressing在其名称中没有“创建”或“复制”,这意味着它不返回(+1)保留的对象。 因此,您必须使用takeUnretainedValue()来获取非托管引用的值。

有关这些命名约定的详细信息,请参阅“Core Foundation内存管理编程指南”中的“ 所有权策略”中的“创建规则”和“获取规则”。

您正在获取CFHostGetAddressing返回的数组的CFHostGetAddressing ,这意味着ARC将插入一个release调用以平衡认为需要平衡的retain调用,而实际上它不需要执行此操作。 您应该使用takeUnretainedValue()而不是takeRetainedValue()作为takeRetainedValue()的名称语义并不意味着您需要获取结果的所有权。

在基本级别, takeRetainedValue()takeUnretainedValue()之间的区别在于前者将指示ARC在变量超出范围时插入release调用,而后者不会。 在语义层面,前者告诉你想要或者需要获取变量的所有权,通常意味着对该对象存在不平衡的retain调用, ARC将平衡。