Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I listen for reachability updates in each UIViewController?

I see a lot of Reachability examples where people only display a message when reachability status changes.
But recently, I saw in Foursquare app that they display a message every time the user try to make an action requiring an Internet connection.
I think this is more robust and a better UX to remind the user he can't do anything without Internet. Mainly because users can switch between apps, do something else and forget he has no connection when he comes back.
Also as soon as they get the connection back I can see that they fetch data from the Internet and refresh the UI.

What I am really looking for is the best way to do this. How this is done?
Do they have a general UIViewController that checks for reachability each time it needs a connection?
Or do they have a kind of proxy class before each Internet request that cancels the request and display a message? How you guys are dealing with that?

Thanks.

EDIT:

The solution I came up with is using AFNetworking which also provide reachability status in the box.
Basically I created an AFHTTPClient and set a reachability callback block on it to listen to status changes. The AFHTTPClient object is application wide (kind of a singleton). (in fact I have one AFHTTPClient per host I need to reach a.com, b.com ...).

Then when I need to perform a request I create a new AFHTTPRequestOperation (AFJSONRequestOperation in my case) and I enqueue it on my AFHTTPClient object. In the failure block of the operation I check to see if the host is reachable with the networkReachabilityStatus property of the AFHTTPClient. If it's unreachable I display a message that there is no internet connection to the user.

I wrapped that up so I don't have to do this each time I create an operation. So now in the app, each time the user try to do something when there is no connection he got a message remembering him that he has no internet access.
I also use the reachability callback to reload data on a screen once I get the connection back (or rather once I am supposed to have a connection).
I don't know if it's best practice but I think it's nice to know that the app takes care of reloading important data as soon as a new connection is available.

If someone is interested by a sample code I can provide it.

like image 758
grandouassou Avatar asked Sep 19 '12 07:09

grandouassou


1 Answers

On a WWDC talk this year the Apple engineer on stage recommended users to never base the application internet access on the Reachability example app status. Often reachability doesn't provide a complete information (it is based on a complex mechanism) and the suggestion provided by the engineer was this:

  1. try to do your internet connection, whatever it is the Reachability status; then set your UI hint based on success/fail result
  2. if it fails due to networking issue, then register to Reachability and retry again when Reachability gives the green light; this is needed when you want to recover automatically from the fail condition
  3. in any case give the user the possibility to "force a retry", whatever is the Reachability status. If it succeeds, reset your UI hint immediately.

What the Apple engineer said is perfectly true: quite often you can see in the console log Reachability failure messages while the internet connection is perfectly alive.

Other thing: there is no better "network hint" than the one displayed in the status bar: if you have there the wi-fi icon, the 3G/4G icon, the cellular field strength.

Returning to your original question: there is no absolute better way to manage this stuff, this depends heavily on the application architecture. In case you prefer to concentrate your networking stuff in a dedicated class (not a UIViewController but a NSObject subclass) then it could make sense to define a read-only property for that class that is updated with "success/fail" after latest internet connection with the servers app (it makes no sense to ping other servers like Google or Apple: first of all it's not elegant, second the issue may come from your the servers that serve the app and not the device internet connection status!).

@property (readonly) BOOL lastConnectionToMyServerSuccess
Then your view controllers can register (by KVO or by central notification) to this property changes and update their UI accordingly by showing an icon or else (I repeat: leave the user the possibility to try manually to connect to the internet). View controllers should unregister from KVO when out of sight ("viewWillDisappear:") or unloaded ("viewDidLoad:") or dealloc'd.

Of course this adds some extra complexities. E.g.: you use the app, the internet light was green. Then you suspend it, do something else and after a few minutes your return to the app. In such case the app should ping your servers to restore the internet light status again, as after a few minutes network conditions could have changed (e.g. you are on a train). In any case all loaded view controllers will get the KVO notification from the network dedicated class and update themselves.

like image 56
viggio24 Avatar answered Nov 15 '22 20:11

viggio24