Updating iPhone Reachability on Network Changes
Asked Answered
O

1

10

Edit 23.5.11

I'm now wondering whether I'm over engineering this. When I use an online connection, I handle it properly - either:

  • in the background with a progress or activity indicator showing and if it fails, I display a suitable message OR

  • I call another application, either Safari or Maps which will then do its own check and fail if there is no connection. That leaves the user in that other app that has failed, which is not perfect tho.

So if I do what I'm suggesting below and standard Reachability returns not reachable and I then have to do a NSURLConnection in case the radios have gone to sleep, then I'm not sure that's any better than just trying to get the online resource in the first place.

If anyone can help - I'd be really grateful. I'm almost ready to submit, just need to get this right.

I'm using Apple's Reachability sample to generally good effect except for when the mobile or cellular connection goes to sleep and then comes back or the wifi goes and the cellular connection is then relied on.

Its fine when the mobile (cellular) connection isn't changing. This is in line with comments I've read, that when the cellular radio switches off you have to wake it up again manually. However, I can't see how to do that.

Do I need to setup a NSURLConnection? Some sample code would be great. When I get a notification that there is no connection, would I send the NSURLConnection and tell the user to try again in a moment and then if I get a callback to say its successful, override the off setting from Reachability?

In addition, would I need to do that whenever there seems to be no connection, just in case its that - this seems wasteful of resources when it may well not be that. e.g.an iPod Touch that's not in wifi reach.

I've also looked at DDG's alternative, but it looks like that will have the same issue.

Any helpful suggestions would be warmly welcomed.

Thanks,

Chris.

Offutt answered 19/5, 2011 at 17:56 Comment(0)
R
13

You cannot and should not use Apple's Reachabilty sample code (or the SCNetworkReachabilityFlags) to determine if a network resource is or will be available. They give you useful tools for giving user feedback about why a connection failed and for determining if and when to retry a connection. However if you want to access a network resource you should just ask for it.

Don't present your users with "no network connection" alerts based on the reachability flags. Perform your network request and if it fails check the reachability flags and your own history of requests to see if you should tell your user that the request failed or silently retry. You shouldn't want or need to spam the user with every network failure. If a request fails consider retrying it if the host seems to be reachable and only report a failure to the user after a couple of attempts or when the reachability flags suggest that you have actually lost your network connection and not just had a single request fail.

As for reactivating the device's radios you'll need to balance your desire to try to fetch network resources with allowing the device to power down the network interfaces to save power. I don't know what your app is trying to do but I'd recommend allowing the device to power down and then trying to connect in response to a user asking the app to fetch new data. I don't see a case where you would want to reactivate a radio just to give the user a hint that some network resource may or may not currently be reachable.

See https://devforums.apple.com/message/409618

The only way to know whether a host is available is to try to connect to it. If that connection fails, you can use reachability to provide feedback to the user, and to guide your retry mechanism, but using reachability to preflight a connection is not a good idea.

The key issue here is that reachability uses local information to determine its results. This doesn't say anything about the state of the wider Internet. The origin server might be down, or any number of links between you and the origin server might be down, and reachability will happily say that it's reachable. At that point you're going to try to connect, and the connection will fail. So you're going to have to handle the error anyway, which means you might as well not do the preflight and let your standard error handling cover this case as well.

Also take a look at this question regarding checking for a resource before loading it using an external application: https://devforums.apple.com/message/411329

Making a HEAD request for the resource should give you a reasonable idea if the external app will be able to load it without requiring you to download a significant amount of data (latency will still be a concern though).

Rancell answered 24/5, 2011 at 0:4 Comment(11)
Wow Jonah - nice, clear and detailed response. Do you teach somewhere?Pirandello
However you can use the Reachability code to be notified when the "reachability status" changes.Jennijennica
Thanks @Rancell - this a great, definitive response. I think your clarity will help a lot of people, as can be seen by the votes we had even before you answered. I'm going to simplify my process significantly now. Thanks again.Offutt
@Alexsander - yes you can, but I'm not sure how reliable that information is.Offutt
@Alexsander, @Chris: The reachability flags give you the device's understanding of available networks. That's a great way to identify that something about the device's network connections changed so that you can "I seem to still have a WWAN connection, I should try to reach that host again" or "I seem to have lost all connectivity, I shouldn't bother trying again right now". It is however not enough to allow you to make statements like "you will be able to download new data now". The only way you can really know if a host is reachable is to try to reach it.Rancell
@forsvarir - I offered the bounty b/c this is a great question that I wanted a good answer to. Jonah appears to have knocked it out of the park, but I wanted to wait just a little longer in case some other heavy-weights wanted to pitch in.Artilleryman
@Rancell - so is there a cost to calling startNotifier and leaving it on for the life of the app?Artilleryman
@Artilleryman I don't believe there's a cost to doing so. You'll be notified when the device detects a change in its network state but I don't think this will change the device's behavior or have any impact on network or power use.Rancell
I don't quite agree. You quote "The key issue here is that reachability uses local information to determine its results. This doesn't say anything about the state of the wider Internet." If that is true, reachability should be an excellent test to assert that the server is currently unreachable and connections are sure to fail. It is understandably no guarantee the connections will succeed if reachability tells you the server is reachable.Phenix
@StevenKramer As I recall, reachability reports the current state of the device's network interfaces but will not change them. That means that if the radio is powered down it will report (correctly) that the device does not have a connection. The device would however establish one if you attempted to send a request. Therefore an "unreachable" response from the reachability APIs alone cannot universally guarantee that a request would fail. Following a failed request reachability checks are a great tool for deciding if it is worth another attempt.Rancell
I was thinking that would be kSCNetworkReachabilityFlagsConnectionOnTraffic. Knowledge of the exact meaning of reachability flags seems to be thinly spread, unfortunately. Right now we have seen a case where the entire network stack is up, Safari downloads over Wi-fi, but our app insists the user is offline...Phenix

© 2022 - 2024 — McMap. All rights reserved.