NWPath.status shows unsatisfied on device, statisfied on simulator

Hello,

I am encountering an issue when attempting to verify access to the internet from WatchOS on a physical device. Running the code below on a physical device always shows "Not Connected." However, running on the simulator shows "Connected."

Three years ago, a similar post was made. https://developer.apple.com/forums/thread/131678

import Foundation
import Network

class NetworkMonitor: ObservableObject {
    
    @Published var isConnected: Bool = false
    @Published var currentNetworkType: NWInterface.InterfaceType = .other
    
    private let monitor = NWPathMonitor()
   
    init() {
        monitor.pathUpdateHandler = { [weak self] path in
            DispatchQueue.main.async {
                self?.networkStatusDidChange(path)
            }
        }
        monitor.start(queue: DispatchQueue.global(qos: .background))
    }
  
    private func networkStatusDidChange(_ path: NWPath) {
        isConnected = path.status == .satisfied
        currentNetworkType = path.availableInterfaces.first?.type ?? .other
    }
    
    deinit {
        monitor.cancel()
    }

}

import SwiftUI

struct ContentView: View {
    
    @ObservedObject var networkMonitor = NetworkMonitor()
    
    var body: some View {
        VStack {
            if networkMonitor.isConnected {
                Text("Connected")
            } else {
                Text("Not Connected")
            }
        }
    }
    
}
code-block

Replies

However, running on the simulator shows "Connected."

In general, there’s no point testing this sort of thing on the simulator. It uses the macOS networking stack, which behaves very differently than the watchOS one. Likewise for the iOS and tvOS simulators.

As to what’s causing your specific problem, I believe that NWPathMonitor is accurately reflecting your app’s access to the network. See TN3135 Low-level networking on watchOS.

Taking a step back, the concept of “access to the Internet” doesn’t make a lot of sense in general, and especially on watchOS. That’s because:

  • The Internet isn’t one thing [1]. You might be able to connect to example.com but not apple.com, say.

  • That ability can come and go from moment to moment.

  • On watchOS specifically, network requests often get proxied by your iPhone, so the watch’s ability to connect to a specific host is irrelevant.

Folks who run into trouble here are often trying to preflight their network connections. This is a mistake. If you need to connect, just connect and then deal with any errors that crop up. Also, consider using an API that waits for connectivity, like NWConnection and URLSession with the waitsForConnectivity flag enabled.

If you’re not using this information to preflight then please explain what you are using it for and I’ll try to suggest a path forward.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Despite what folks might tell you…

https://www.youtube.com/watch?v=iDbyYGrswtg

  • +1 for avoiding preflight behavior, especially on watchOS.

Add a Comment

Thank you for your reply.

No, the intention is not for preflight checking but to show a network connectivity indicator in the watch app. We have received user requests for such an indicator.

the intention is … to show a network connectivity indicator in the watch app.

I don’t think there’s a good way to do that. Such efforts are, in general, best left to the system.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"