networking连接检查在Swift中的IPv6networking上崩溃
我最近因为不兼容IPv6而被拒绝了一个应用程序。 下面的代码被调用时,该应用程序导致崩溃。 我怀疑是因为当Applebuild议不再使用它时,它使用了SCNetworkReachabilityCreateWithAddress
。
任何人都可以帮我一把,帮助使这个代码与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 } }
代码来源:
检查在斯威夫特的互联网连接的可用性
代码调用在视图上加载:
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 }
从苹果关于支持纯IPv6networking的文档 :
无预检连接
可达性API(请参阅SCNetworkReachability参考 )用于识别连接问题之后的诊断目的。 许多应用程序错误地使用这些API来主动检查Internet连接,方法是调用
SCNetworkReachabilityCreateWithAddress
方法并将0.0.0.0的IPv4地址传递给networking,这表明networking上有路由器。 但是,路由器的存在并不能保证存在Internet连接。 通常,避免预检networking可达性。 只要尝试build立连接并妥善处理失败。 如果您必须检查networking可用性,请避免调用SCNetworkReachabilityCreateWithAddress
方法。 调用SCNetworkReachabilityCreateWithName
方法并将其传递给主机名。
你的应用程序似乎在做这两个build议:
- 使用可达性API执行预检,而不是仅在发生连接问题时才执行。
- 将IPv4文字传递给可达性API而不是主机名。
为了解决这个问题,我build议不要先检查networking连接,而是处理来自networking代码的错误。
你正在崩溃,因为你在代码中显示一个警告,应该在主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 } })
尝试这个:
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) }