2016-07-22 108 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) 
     }