Code: Reachability

Whoops, here’s something we’d overlooked in our latest app effort — good thing we stumbled across this before submitting it! — if your application is network dependent, apparently Apple requires that you detect network availability proactively, spinning helplessly in its absence is not sufficient. From this top 11 list of rejection reasons:

6. Popup for network detection If your app requires the use of the Internet, you must detect when the network is unavailable and provide a pop-up message informing the user. Just having the spinning busy icon display and a message saying “trying to connect” is not sufficient. Apple will reject your app if you don’t provide a message informing the user that they need a network connection.

Ah, OK then. No worries, we’ll just grab the Reachability sample … wait, what?

7. False claims of a missing network On a related note, make sure you don’t have any false positives in your network detection. There’s a bug in the “reachability” functions provided by Apple. If you don’t first try to perform a network connection but instead just do a reachability test, the code will always report the network is unavailable. Apple will reject your app if they discover you have this false positive case.

Actually, it looks like what I presume is the “bug” referred to above in Reachability is indeed not such … not exactly, anyways. The trick is, you want your first status check of your target host name’s reachability to be made synchronously. Because, until it completes the check, well, it’s not connected, is it now? Quite logical, really. And once that initial check is sorted, then your updates should properly be asynchronous. So in Reachability’s appDelegate where it has

that’ll always return false for your target host reachability in -updateStatus if you follow the given instructions. Whoops! To fix that, simply do a synchronous then an asynchronous query

… and you’re all good.

It would be more clear that the first host reachability check failing was a foreseeable occurrence if -setNetworkStatusNotificationsEnabled was actually labelled -setStatusResultsAsynchronous. Or, even better,
-callThisToMakeTheSampleFailHaHaSucka. But Apple very rarely labels sample code quite that honestly!

Alex | May 1, 2009
  • Paul Robinson May 2, 2009 at 4:30 am
    Nice tip. Thanks for posting this.
  • Aatif May 5, 2009 at 2:58 am
    thanks, can u or somebody suggest the minimum required stuff to add a 'check' for internet connectivity in my existing application?
  • luk May 16, 2009 at 10:39 am
    Your solution helps as you described - but when I put this in my application I'm not getting notification when connectivity was changed
  • quack May 16, 2009 at 11:16 pm
    there isn't a bug in apples code there's an issue with the sample. don't think the whole file was meant to be cut and pasted. use the SCNetwork functions they call in the example.
  • Anonymous May 17, 2009 at 1:16 am
    Problem with this sample is with the cache (reachabilityQueries). When we first set NetworkStatusNotificationsEnabled to NO then the value of SCNetworkReachabilityRef will be cached but if we chanaged notification to YES, the notification won't by registered in current run loop. In my solution I added property to the ReachabilityQuery - networkstatusnotificationenabled - and a method to the Reachability which I call after changing networkStatusNotification; the method: - (BOOL)updateNetworkStatusNotification { if (![self hostName] || ![[self hostName] length]) { return NO; } ReachabilityQuery *cachedQuery = [self.reachabilityQueries objectForKey:[self hostName]]; if(cachedQuery.networkStatusNotificationsEnabled != [self networkStatusNotificationsEnabled]){ [cachedQuery scheduleOnRunLoop:[NSRunLoop currentRunLoop]]; } return YES; } so from client code we have: [[Reachability sharedReachability] setHostName:[self hostName]]; [self updateStatus]; [[Reachability sharedReachability] setNetworkStatusNotificationsEnabled:YES]; [[Reachability sharedReachability] updateNetworkStatusNotification];

Leave a Reply