Reachability fails after no network situation - how to properly use the ability to increase performance asynchronously

I encountered a very strange crash with my iPhone app in development. It seemed that every time I show my application to a friend, it crashes, but otherwise it will never crash. After I was completely puzzled by the aspect of Murphy's Law, I determined the structure of the failures - the New York subway. My application crashes sequentially after I use the metro. I traced this issue to using Reachability . The application will crash the next time after it is used in a network situation (not including airplane mode). I follow Apple's recommendations and check the connection with Reachability before performing any other network operations, but I found some conflicting documents on how to call them.

I am currently 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 call synchronously with the method called from viewDidAppear.

  if ([self reachable]== YES) { ... do network stuff ... 

which is based on the code from the Reachability Guide for iOS 4

My question is: is there a proper use of Reachability that will take care of this error and cope with the lack of a 3G network or Wi-Fi? Do I need to create another thread or do something to remove a synchronous call?

Here, by the way, is the crash log that I see when my application crashes, which makes me think that this is 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
+7
source share
2 answers

In the synchronous case, you are likely to be killed by the IOS Application Watchdog. This is because, to check for availability, the SCNetworkReachability function must perform a DNS lookup, which can take up to 30 seconds. If the availability check is on the main thread (i.e. In viewDidAppear), you block the main thread for a potentially long time, iOS believes that your application freezes and the applicationโ€™s watchdog kills it after 20 seconds.

Apple even warns about this in the Reacahbility sample code:

Apple README Authentication Code

Just use notifications, for example, in the Reachability application example - it works well and quite simply as soon as you look at the NSNotificationCenter design pattern.

Good luck

+4
source

I solved my problem by setting it as asynchronous. I call such a method

 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSTimer *timer = [NSTimer timerWithTimeInterval:0 target:self selector:@selector(loadData) userInfo:nil repeats:NO]; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; [pool release]; 

and the method called looks something like this:

 - (void)loadData { // check for reachability first before starting data load if ([self reachable]== NO) { // display error message that there is no internet connection, eg UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:@"Connection Error" message:@"Cannot load data. There is no internet connection." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Retry",nil]; [errorAlert show]; [errorAlert release]; } else { // do something to load data from internet ... } } 

using the same available code as above.

I would say I always use Reachability, as this - the example that Apple gives is incomplete. This code has been working for me in the completed application for several months, and it was very stable.

EDIT: This code is no longer stable with iOS 5 - now it can sometimes crash due to "active claims in a reasonable amount of time." Apple has updated their documentation and sample code since I wrote this question, so I suggest the following link in another answer.

-one
source

All Articles