Network connection failure on IPv6 networks in Swift

I recently got an application rejected for incompatibility with IPv6. The application crashed when the following code was called. I suspect the crash is due to the fact that it uses SCNetworkReachabilityCreateWithAddress when Apple recommends no longer using it.

Can someone give me a hand and help make this code below compatible with IPv6 and IPv4?

the code

 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 } } 

Source code:

Check for internet connectivity in Swift

Call code for viewing loaded:

 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 } 
+1
ios swift ipv6
source share
4 answers

From Apple IPv6-only Network Support Documentation :

Connect without pre-flight

Reachability APIs (see SCNetworkReachability Link ) are for diagnostic purposes after identifying a connection problem. Many applications incorrectly use these APIs to proactively check the Internet connection by calling the SCNetworkReachabilityCreateWithAddress method and passing it an IPv4 address of 0.0.0.0, which indicates the presence of a router on the network. However, having a router does not guarantee an internet connection. In general, avoid pre-checking network availability. Just try to establish a connection and gracefully handle failures. If you want to check for network availability, do not call the SCNetworkReachabilityCreateWithAddress method. Call the SCNetworkReachabilityCreateWithName method and pass it the host name.

Your application seems to fulfill both sides that it recommends:

  • Using reachability APIs to perform preflight, and not just in case of a connection problem.
  • Passing literature on IPv4 reachability APIs, not hostnames.

To solve this problem, I would recommend not checking the network connection in front, but instead processing errors from your network code.

+1
source share

You get a failure because you are showing a warning inside this code that should run in the main user interface thread. Put your user interface code inside dispatch_async going to the main user interface thread and it should fix the problem.

 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 } }) 
+1
source share

Try the following:

 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) } 
+1
source share
 func isConnectedToNetwork() -> Bool { var zeroAddress = sockaddr_in() zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress)) zeroAddress.sin_family = sa_family_t(AF_INET) let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) { $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress) } } //Commented code only work upto iOS Swift 2.3 // let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) { // // SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)) // } 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) 

}

0
source share

All Articles