Alamofire: NetworkReachabilityManager doesn't work with .notReachable

I have an issue with NetworkReachabilityManager from Alamofire. I tried to test the connection with this example code:

    let manager = NetworkReachabilityManager(host: "www.apple.com")
    
    manager?.listener = { status in
        
        switch status {
            
        case .notReachable:
            print("network connection status - lost")
        case .reachable(NetworkReachabilityManager.ConnectionType.ethernetOrWiFi):
            print("network connection status - ethernet/WiFI")
        case .reachable(NetworkReachabilityManager.ConnectionType.wwan):
            print("network connection status - wwan")
        default:
            break
        }
    }
    manager?.startListening()

What did you expect to happen?

I tested the app on my devices (iPhone 6 / 7, iPhone 6+) and simulator on XCode.

1st testing:

  • Before I launched the app I turned off the wifi and launch the app and I checked the console on the XCode output. I expected to see: network connection status - lost

2nd testing

  • Before I launched the app I turned on the wifi and launch the app and I checked the console on the XCode output. I expected to see: network connection status - ethernet/WiFI or network connection status - wwan

What happened instead?

1st testing:

  • Before I launched the app I turned off the wifi and launch the app and I checked the console on the XCode output. I received no response at all. (FAILED) It is supposed to show the response: network connection status - lost

2nd testing:

  • Before I launched the app I turned on the wifi and launch the app and I checked the console on the XCode output. I received response: network connection status - ethernet/WiFI or network connection status - wwan (CORRECT)

I tested many times and sometime it response both network connection status - lost and network connection status - ethernet/WiFIon the same time. Which is very weird. I tried to use a different Reachability.swift from other open source and it returned perfect response exactly what I expected.

Do you think we have a bug in NetworkReachabilityManager from Alamofire for this issues what I discovered? I didn’t even add other methods in my project just simple method what you provided on Alamofire. I tried to add those code in UIViewController or in a singleton class both of them have the same issues no response so far. Any idea what is wrong with .notReachable? Any suggestion appreciated.

Alamofire Environment

Alamofire version: 4.5 Xcode version: 8.3.3 Swift version: 3.1

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 11
  • Comments: 32 (4 by maintainers)

Most upvoted comments

Also having issue with the NetworkReachabilityManager. I start iOS 11 simulator with internet connection, turn off mac wifi, receive notification for connection status change. Turn on it again and getting stuck in “no internet” state. The NetworkReachabilityManager doesn’t pick up new state.

Hello all,

First off, I want to apologize for the time it has taken for us to properly address this issue. We should have addressed all the comments here in a much more timely manner.

With that said, we’ve been working on a fix that is currently up in #2688. I want to also take some time to try and address the various issues and behaviors that have been posted here. It’s important that everyone understand why and how some of these issues come to light.

Reported Issues

No Notifications

If you are not receiving any notifications in your listener closure, then there are a couple things you may have done incorrectly.

  1. You didn’t call the startListening API on the manager
  2. You didn’t retain the manager

Both of these will result in your closure not being called.

Simulators

As with many network related operations, the simulators do not have the same behavior as devices when testing reachability. I’ve been extensively testing the behavior of reachability on the simulators over the past couple of days, and I can tell you, that since iOS 10, reachability behavior is broken.

Some of you have reported that you can get “stuck” in a .notReachable state when running on the simulator. I can report that that issue exists on iOS 10, 11, and 12 simulators. Unfortunately, when running in the simulator and toggling WiFi off, then back on, that the reachability APIs do not report that connectivity was restored. They continue to return reachability flags of 0. This is not an issue with the code in Alamofire, but instead with the runtime behavior of the simulators. Unfortunately, there is nothing we can do to fix this issue in Alamofire.

Therefore, if you are trying to test your functionality written against reachability, we highly recommend you test on device.

Stuck on .notReachable

Issue #2677 was recently reported and identified a bug in the logic for setting the previousFlags value in the NetworkReachabilityManager. The listener closure was not being called when launching the app in airplane mode without a WiFi connection. The reason for this was a bad initial value set on the previousFlags property. That issue has been resolved in #2688. I’ve been testing the behavior of the changes in #2688 and everything is working as expected on devices running iOS 10, 11, and 12. I do not have any iOS 9 devices, but I would assume everything is working there as well.

If anyone has an iOS 9 device and would be willing to test out the sample app for us, we’d greatly appreciate it!

Listener Closure Behavior

The listener closure behavior seems to be a bit misunderstood in this thread, so I want to clarify how it is intended to work. The listener closure should always be called when the startListening API is called. It simply reports the initial status to the closure. From then on, it will always be called when the status changes.

You can also get the current status at any time by calling the networkReachabilityStatus property or the isReachable convenience APIs.

Host Reachability

@dennishylau you seem to think that isReachable should be able to verify whether your dev server is actually up and running or not. That is not what the reachability APIs are intended to be able to tell you. You would need to make HEAD requests against your dev server to be able to identify that.

The reachability APIs are designed to tell you whether your connection, or host, are in fact reachable and in what way. Therefore, if you want to know if your connection itself is reachable, then you should use the initializer that does not require a host. If you want to monitor a specific host, then provide a host name (make sure to omit the http(s)://). From what we can tell, the host initializer will most likely add a DNS lookup to make sure your hostname can be mapped to an address. It does not actually hit your server to verify it’s actually up and running.

The DNS lookup info here is speculation. We couldn’t find anything specific about the underlying behavior in the documentation.

Summary

Hopefully the descriptions of the various issues help clarify how the functionality should work. If anyone has any further questions, please feel free to post them here, or on #2688. I’m going to go ahead and close this issue out since all the reported issues have either been resolved in #2688 or explained as to what was causing the issue.

Cheers. 🍻

retaining the manager solved the problem for me.

It didn’t solve it for me. The listener is not being called when you turn your wifi back on. Only gets called when it gets turned off.

Any update of this? I have the same issue.

Had similar Problems with a host that also contained the scheme (https:// in my case). It briefly reported as connected and immediately fired as non-connected. Removing the scheme (and with it the “/” as @mevdev mentioned) resolved the issue

Thanks for all the in-depth info here everyone, we’ll investigate. I’ll ping the thread again once I have more info.

retaining the manager solved the problem for me.

I am trying to use multiple NetworkReachabilityManager objects to monitor external services.

They are all up. This is my output (with ‘Internet’ being www.apple.com)

Service: Internet: reachable(Alamofire.NetworkReachabilityManager.ConnectionType.ethernetOrWiFi)
Service: ABC: reachable(Alamofire.NetworkReachabilityManager.ConnectionType.ethernetOrWiFi)
Service: ABC: notReachable
Service: O365: reachable(Alamofire.NetworkReachabilityManager.ConnectionType.ethernetOrWiFi)
Service: O365: notReachable
Service: CC: reachable(Alamofire.NetworkReachabilityManager.ConnectionType.ethernetOrWiFi)
Service: Internet: reachable(Alamofire.NetworkReachabilityManager.ConnectionType.ethernetOrWiFi)
Service: CC: reachable(Alamofire.NetworkReachabilityManager.ConnectionType.ethernetOrWiFi)
Service: CC: notReachable
Service: Internet: reachable(Alamofire.NetworkReachabilityManager.ConnectionType.ethernetOrWiFi)

It really seems like this part of AlamoFire is broken. I’d rather not pull in another library so I may take a crack at Apple’s Reachability Manager.

EDIT: It seems if the URL has any “/” characters really funny stuff will happen. It will report as reachable then immediately after it will report as .notReachable

Assigning to @cnoon, as he wrote this code and is most familiar with expected reachability behavior.