2016-07-22 378 views
1

我最近因爲與IPv6不兼容而被拒絕。當下面的代碼被調用時,該應用程序導致崩潰。我懷疑這次崩潰是因爲當Apple建議不再使用它時,它會使用SCNetworkReachabilityCreateWithAddressSwift中的IPv6網絡上的網絡連接檢查崩潰

任何人都可以給我一個幫助,使這個代碼低於兼容IPv6和IPv4?

代碼

import Foundation 
import SystemConfiguration 

public class Reachability { 

    class func isConnectedToNetwork() -> Bool { 

     var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0)) 
     zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress)) 
     zeroAddress.sin_family = sa_family_t(AF_INET) 

     let defaultRouteReachability = withUnsafePointer(&zeroAddress) { 
      SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)).takeRetainedValue() 
     } 

     var flags: SCNetworkReachabilityFlags = 0 
     if SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) == 0 { 
      return false 
     } 

     let isReachable = (flags & UInt32(kSCNetworkFlagsReachable)) != 0 
     let needsConnection = (flags & UInt32(kSCNetworkFlagsConnectionRequired)) != 0 

     return isReachable && !needsConnection 
    } 

} 

代碼源:上視圖

Check for internet connection availability in Swift

代碼呼叫沒有負載:

if Reachability.isConnectedToNetwork() == false 
{ 
     // internet is down 
     let error = NSError(domain: "", code: 3, userInfo: nil)   let alertView = createDefaultAlertError(error.code) 
     let tryAgainAction = UIAlertAction(title: ClassGeneralMessages().userMessageTryAgain, style: UIAlertActionStyle.Default) { (UIAlertAction) in     
} 
else 
{ 
    // internet is ok 
    // run more code here 
} 
+0

請出示你的代碼,當你調用該函數。 –

+0

@ Christian Abella,代碼補充說。 – GuiSoySauce

+0

我面臨同樣的拒絕問題。你能解決這個問題,以及如何?請提出建議。 –

回答

1

Apple's documentation on supporting IPv6-only networks

連接而無需預檢

可達性的API(見SCNetworkReachability Reference)被識別連接問題後,用於診斷目的。許多應用程序錯誤地使用這些API來主動檢查Internet連接,方法是調用SCNetworkReachabilityCreateWithAddress方法並將0.0.0.0的IPv4地址傳遞給它,這表明網絡上有路由器。但是,路由器的存在並不能保證存在Internet連接。通常,避免預檢網絡可達性。只要嘗試建立連接並妥善處理失敗。如果您必須檢查網絡可用性,請避免撥打SCNetworkReachabilityCreateWithAddress方法。調用SCNetworkReachabilityCreateWithName方法並將其傳遞給主機名。

你的應用程序似乎是做兩件事就建議不要:

  1. 使用可達API來進行預檢,而不是隻在連接問題的事件。
  2. 將IPv4文字傳遞給可達性API而不是主機名。

爲了解決這個問題,我建議您不要先檢查網絡連接,而是處理網絡代碼中的錯誤。

+0

我已經對這個問題進行了一些更新。該應用程序再次遭到拒絕。我正在關注Apple的文檔。另外,不要先檢查連接。如您所說,所有網絡錯誤都由CloudKit操作處理。我正在爲使用xCode 7.3.1的iOs9構建。完全迷失在這一個。 – GuiSoySauce

+0

你不只是做了一些小的更新,[你完全改變了問題](http://meta.stackexchange.com/questions/43478/exit-strategies-for-chameleon-questions)! – bdash

+0

它被還原爲對您的答案更有意義的那個@bdash – GuiSoySauce

1

由於您在代碼中顯示警告,因此您會在主UI線程中運行崩潰。將你的用戶界面代碼放入dispatch_async進入主UI線程,它應該解決這個問題。

dispatch_async(dispatch_get_main_queue(), 
{ 
    let error = NSError(domain: "", code: 3, userInfo: nil)   let alertView = createDefaultAlertError(error.code) 
     let tryAgainAction = UIAlertAction(title: ClassGeneralMessages().userMessageTryAgain, style: UIAlertActionStyle.Default) { (UIAlertAction) in } 
}) 
+0

如果在IPv4上發生錯誤,警報視圖會彈出而不會崩潰。這讓我覺得它不是UI相關 似乎'isConnectedToNetwork'被調用時檢查IPv6網絡崩潰 這是我認爲蘋果正在喋喋不休:確保您沒有通過點符號傳遞IPv4地址文字到API,如getaddrinfo和SCNetworkReachabilityCreateWithName。相反,請使用高級網絡框架和API的地址無關版本(例如getaddrinfo和getnameinfo),並向它們傳遞主機名或完全限定的域名(FQDN)。請參閱getaddrinfo(3)Mac OS X Dev .. – GuiSoySauce

+0

如果您(GulSoySauce)將直接從Apple'指南和樣本註釋'中引用,則應將其放在引號中並提供完整參考。否則它是抄襲!所有來自「確保您不是......」的文本都來自Apple文檔。只是說。 – PhilipS

1

試試這個:

class func isConnectedToNetwork() -> Bool 
     { 
      var zeroAddress = sockaddr_in6() 
      zeroAddress.sin6_len = UInt8(MemoryLayout.size(ofValue: zeroAddress)) 
      zeroAddress.sin6_family = sa_family_t(AF_INET6) 

      let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) { 
       $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in 
        SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress) 
       } 
      } 

      var flags = SCNetworkReachabilityFlags() 
      if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) { 
       return false 
      } 
      let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0 
      let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0 
      return (isReachable && !needsConnection) 
     }