I was encountering a very strange crash with my iPhone app in development. It seemed that every time I'd show my app to a friend it would crash, but it would never crash otherwise. After being generally mystified by the Murphy's Law aspect, I've determined the pattern of crashes -- the New York City subway. My app crashes consistently after I use the subway. I've traced the problem to my use of Reachability
. The app crashes the next time after it is used in a no network situation (not including airplane mode). I'm following Apple's guidelines and checking for for a connection with Reachability
before I do any other network operations, but I've found some conflicting documentation about how to call it.
Currently I'm doing something like this:
-(BOOL)reachable {
Reachability *r = [Reachability reachabilityWithHostName:@"www.stackoverflow.com"];
NetworkStatus internetStatus = [r currentReachabilityStatus];
if(internetStatus == NotReachable) {
return NO;
}
return YES;
}
which I'm calling synchronously with a method called from viewDidAppear.
if ([self reachable]== YES) {
... do network stuff ...
which is based on the code from Reachability Guide for iOS 4
My question: is there proper use of Reachability
that will take care of this error and handle the absence of a 3G or Wifi network? Do I need to be spawning another thread or do something to remove a synchronous call?
Here, by the way, is the crash log that I see when my app crashes, which leads me to think that it's a synchronous/asynchronous problem.
Application Specific Information: (app name) failed to resume in time Elapsed total CPU time (seconds): 3.280 (user 1.770, system 1.510), 33% CPU Elapsed application CPU time (seconds): 0.040, 0% CPU Thread 0 name: Dispatch queue: com.apple.main-thread Thread 0: 0 libsystem_kernel.dylib 0x30747fbc kevent + 24 1 libsystem_info.dylib 0x30abec4e _mdns_search + 586 2 libsystem_info.dylib 0x30abfb72 mdns_addrinfo + 370 3 libsystem_info.dylib 0x30abfd68 search_addrinfo + 76 4 libsystem_info.dylib 0x30ac1bcc si_addrinfo + 1080 5 libsystem_info.dylib 0x30abd0b2 getaddrinfo + 78 6 SystemConfiguration 0x311b4256 __SCNetworkReachabilityGetFlags + 962 7 SystemConfiguration 0x311b4f1e SCNetworkReachabilityGetFlags + 98
In the synchronous case, you're probably being killed by the iOS Application Watchdog. That's because to do the reachability check, the SCNetworkReachability functionality needs to do a DNS lookup which can take up to 30 seconds. If check reachability on the main thread (i.e., in viewDidAppear) you block the main thread for a potentially long time, iOS thinks your app is hung and the application watchdog kills it after 20 seconds.
Apple even warns about this in the Reacahbility sample code:
Apple Reachability Sample Code README
Just use notifications like in the Reachability sample app --- it works well and is pretty straightforward once you grok the NSNotificationCenter design pattern.
Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With