2015-12-28 52 views
2

我剛把自己扔進了iOS開發中,我目前在函數CFRelease中發現了一個運行時錯誤,只是在queryServer函數的末尾(我對get突出顯示),如果我註釋掉函數調用來提取IPFromQuery,我沒有錯誤。在離開示波器時,CFRelease發生Swift崩潰

下面的代碼是服務器的名稱,並返回到該服務器的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 
} 
+1

調用'queryServer'時你傳遞了一個有效的服務器名嗎? – Cristik

+0

代碼確實有效,並且ips被填充了一堆地址 –

+0

因爲這在離開if範圍時崩潰了,那麼這意味着它與範圍內使用的變量之一有關:'hostRef'或結果'CFHostGetAddressing'。 – Cristik

回答

3

CFHostGetAddressing沒有在它的名字, 這意味着它不返回(+1)保留的對象「創建」或「複製」。 因此,您必須使用takeUnretainedValue()來獲取非託管引用的值 。

有關這些命名約定的更多信息,請參閱「內存管理編程指南爲核心基金會」,在「創建規則」和「獲取規則」在Ownership Policy

+0

謝謝你和@Cristik,已經解決了我的問題。 –

2

您正在通過CFHostGetAddressing返回的數組,這意味着ARC將插入一個release通話平衡retain調用認爲需要的所有權要進行平衡的時候,其實它並不需要這樣做。您應該使用takeUnretainedValue()而不是takeRetainedValue(),因爲CFHostGetAddressing的名稱語義並不意味着您必須獲得結果的所有權。

在基本層面,takeRetainedValue()takeUnretainedValue()之間的區別在於,前者將指示ARC插入release呼叫時,變量獲取的超出範圍,而後者不會。在語義層面上,前者告訴你需要或需要接受變量的所有權,通常意味着該對象上存在不平衡的retain調用,其中ARC將平衡。