Я только что погрузился в разработку для iOS, и в настоящее время у меня появляется ошибка времени выполнения в функции CFRelease только в конце функции queryServer (я помещаю комментарий к выделенной строке), и у меня нет ошибки если я закомментирую вызов функции для извлечения IPFromQuery.

Приведенный ниже код берет имя сервера и возвращает ему список 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
Joshua Waring 28 Дек 2015 в 09:50

2 ответа

Лучший ответ

CFHostGetAddressing не содержит "Создать" или "Копировать" в названии, что означает, что он не возвращает (+1) сохраненный объект. Поэтому вам нужно использовать takeUnretainedValue(), чтобы получить значение неуправляемой ссылки.

Дополнительные сведения об этих соглашениях об именах см. В разделах «Правило создания» и «Правило получения». в Политике владения в «Руководстве по программированию управления памятью для Core Foundation».

3
Martin R 28 Дек 2015 в 07:16

Вы становитесь владельцем массива, возвращаемого CFHostGetAddressing, а это означает, что ARC вставит вызов release, чтобы сбалансировать вызов retain, который считает необходимым сбалансировать, хотя на самом деле этого делать не нужно. Вам следует использовать takeUnretainedValue() вместо takeRetainedValue(), поскольку семантика имени CFHostGetAddressing не подразумевает, что вы обязаны брать на себя ответственность за результат.

На базовом уровне разница между takeRetainedValue() и takeUnretainedValue() состоит в том, что первый инструктирует ARC вставить вызов release, когда переменная выходит за пределы области видимости, а второй - нет. На семантическом уровне первый сообщает, что вы хотите или должны стать владельцем переменной, обычно это означает, что для этого объекта существует несбалансированный вызов retain, который уравновесит ARC.

2
Cristik 28 Дек 2015 в 07:06