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

时间:2015-12-28 06:50:42

标签: ios swift

我刚刚投入到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<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
}

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:2)

您正在获取CFHostGetAddressing返回的数组的所有权,这意味着ARC会插入release来调整retain调用,该调用需要进行平衡,实际上它并不需要这样做。您应该使用takeUnretainedValue()而不是takeRetainedValue(),因为CFHostGetAddressing的名称语义并不意味着您需要获得结果的所有权。

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