The incorrect behavior of SCNetworkReachability

I have a problem with the different behavior when using SCNetworkReachability if the iPhone is running a packet tunnel based on NEPacketTunnelNetwork

        var flags: SCNetworkReachabilityFlags =
SCNetworkReachabilityFlags(rawValue: 0)
        let isReachable = flags == .reachable
        let needsConnection = flags == .connectionRequired
        return isReachable && !needsConnection

if I use the [let isReachable = flags == .reachable],

The resulte of isReachable will be False


However,if I use the code of [let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0] like below.

The result will be True

        var flags: SCNetworkReachabilityFlags =SCNetworkReachabilityFlags(rawValue: 0)
        let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
        let needsConnection = flags == .connectionRequired
        return isReachable && !needsConnection


The API reference the [reachable] and [kSCNetworkFlagsReachable] has the same describe :

"The specified node name or address can be reached using the current network configuration"


Can anybady tell me which one is the correct behavior that should be used?

Replies

Try using the contains() to check for the existence of a set flag in SCNetworkReachabilityFlags. For example:


let isReachable = flags.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
let isReachableOnWWAN = flags.contains(.isWWAN)


Another API you could also evaluate as an alternative to SCNetworkReachability would be NWPathMonitor. NWPathMonitor provides an API to fetch the current network path and receive updates when the network path changes.


let nwPathMonitor = NWPathMonitor() 
nwPathMonitor.pathUpdateHandler = { path in 
    
    if path.usesInterfaceType(.wifi) {  
        os_log("Path is Wi-Fi") 
    } else if path.usesInterfaceType(.cellular) { 
        os_log("Path is Cellular") 
    } else if path.usesInterfaceType(.wiredEthernet) { 
        os_log("Path is Wired Ethernet") 
    } else if path.usesInterfaceType(.loopback) { 
        os_log("Path is Loopback") 
    } else if path.usesInterfaceType(.other) { 
        os_log("Path is other") 
    } 
} 
nwPathMonitor.start(queue: .main)


Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com