3

I am using the new "Network" library introduced in iOS 12, but I can't figure out why the network status does not get updated to .satisfied after user gets connected.

here is the code so far:

import Network

class MapViewController: UIViewController {

    let networkMonitor = NWPathMonitor()
    let queue = DispatchQueue(label: "NetworkMonitor")

    override func viewDidLoad() {
        super.viewDidLoad()

        // check for internet connection
        networkMonitor.pathUpdateHandler = { path in
            if path.status != .satisfied {

                // alert the user to check internet connection
                let alert = UIAlertController(title: "Internet Error", message: "Unable to connect. Please check your internet connection.", preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
                alert.addAction(UIAlertAction(title: "Retry", style: .default, handler: { (action) in
                    // TODO: after retry should update status but its not updated
                    print("Status after retry: \(path.status)")
                }))
                self.present(alert, animated: true, completion: nil)
            } else {
                print(path.status)
            }
        }


        networkMonitor.start(queue: queue)
     }
}

To replicate the lost connection situation in simulator, I turn off wifi connection before the view loads, when the alert shows up, tap retry. Surprisingly Status after retry stays .unsatisfied. Why status does not get updated ?

The goal is to tap "Retry" and if user is still not connected keep showing the alert, when user gets connected and tap retry alert should be dismissed.

In order to have an easy network monitor setup you can check this tutorial: https://medium.com/@rwbutler/nwpathmonitor-the-new-reachability-de101a5a8835

Please note that I don't specify network type when instantiating NWPathMonitor(), therefore it detects all types of connections.

mfaani
  • 33,269
  • 19
  • 164
  • 293
Ali_C
  • 215
  • 3
  • 11
  • So you turn off wifi before the view loads, see the alert, then turn wifi back on, then tap the retry button? – David Steppenbeck Sep 08 '19 at 12:14
  • @DavidSteppenbeckPhD yes, and after that if user is not connected when hitting retry, keep repeating the alert until he gets connected. – Ali_C Sep 08 '19 at 12:19
  • 3
    I have not used the Network library, but I have done similar tests (switching wifi on/off) with Reachability framework. One thing that caused a problem was actually testing on the simulator - the notifications were unreliable. However, everything worked on a real device. So, first thing I'd suggest is checking it on a real device. – David Steppenbeck Sep 08 '19 at 12:25

1 Answers1

6

NWPath is a struct, so therefore it is immutable. It won't change within a given invocation of pathUpdateHandler.

Once a network path becomes available you will get a subsequent invocation of pathUpdateHandler with an .satisfied status.

From a user-experience point of view it probably isn't a great approach to show a modal alert. You would typically indicate that the network connection is unavailable using some other indicator - a toast or icon - that disappears or changes once the network is available.

Alternatively or additionally use .waitsForConnectivity on your connection.

Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • I agree that it might not be the best UX approach to show alert, however I have instruction to implement the exact UX with alert, so that can not be changed. I am still in the dark. if NWPath won't change within a given invocation then how it can be useful at all ? By looking at the apple docs, I only see three cases, .satisfied - .unsatisfied and .requiresConnection. I cant seem to find .available and .waitsForConnectivity. Are we both looking at the same library ? – Ali_C Sep 08 '19 at 11:10
  • 2
    Sorry, `.available` was a typo on my part. `.waitsForConnectivity` is a property you set on your network connection; See https://developer.apple.com/videos/play/wwdc2018/715/ The UX issue you have is that "retry" isn't really going to resolve the issue. What you can do is use your path monitoring to update a property that indicates whether there is a network connection. Then when the user attempts network operation you check the property and if it isn't `.satisfied` you show your alert. Then you can check this property, which may have been updated if the user has connected – Paulw11 Sep 08 '19 at 11:21
  • I see your point. I did create a var to keep track of my networkStatus with a value observer, in that value observer I check if it's satisfied I show the alert. The only problem is now repeating the alert(Retry) if user is still notConnected. How do I achieve that ? – Ali_C Sep 08 '19 at 12:17
  • 2
    Retry should be related to whatever network operation you are attempting, not the status of the network itself. When you attempt the network operation, check your property and show the alert if necessary. That way when you retry the network operation you will check the property again and show the alert again if necessary. If no network operation is being attempted then a change in network status shouldn't show the alert, it should just update the property. . – Paulw11 Sep 08 '19 at 12:25
  • 1
    Really though you should push back against this UX. Apple specifically advises against pre-flight network checks since the network status can change at any time. Network availability "now" is no guarantee that a network operation is going to be successful in a second, so you need to handle network errors anyway. This is what I mean when I say that the retry alert should be linked to the network operation, not the network status. – Paulw11 Sep 08 '19 at 12:31
  • Agree with @Paulw11 that UX should connected with per request but not connections state in general. Any thoughts how to implement this? Don't want pass through all project's code and add error handling manually. – Mering May 03 '23 at 15:30