As mentioned by others, reachability detects changes in your hardware instead of the real availability of a server. After reading many posts, I came up with this code.
Here is a full implementation of a ReachabilityManager class that uses both Reachability and URLConnection to make sure that the connection is available or not. Please note that depends on the Reachability classes (I am using the Tony Million implementation but I am sure it works with the Apple one)
If you test this in the simulator and enable/disable your wireless connection you will see that it detects (sometimes takes a few seconds) the connection/disconnection. Something that before with just the reachability class did not work.
I have also added a couple of notifications that are more effective than the ones from Reachability for the rest of your code. You may want to handle this in a different way.
Also, this is a singleton so you can instantiate if from anywhere. You can convert it to a non static class and instantiate it from the AppDelegate.
If a reader has time to create some UnitTests for it, let me know, so we can share more knowledge around the Reachability.
Just create a new NSObject class and copy this contents:
.h
#import <Foundation/Foundation.h>
@interface ReachabilityManager : NSObject
+ (void)startReachabilityWithHost : (NSURL *)hostName;
@end
.m
#import "ReachabilityManager.h"
#import "Reachability.h"
@implementation ReachabilityManager
static ReachabilityManager *_sharedReachabilityManager;
static Reachability *reachability;
static NSURL *_hostName;
static BOOL isServerReachable;
+ (void)initialize
{
static BOOL initialized = NO;
if(!initialized)
{
initialized = YES;
_sharedReachabilityManager = [[ReachabilityManager alloc] init];
}
}
+ (void)startReachabilityWithHost : (NSURL *)hostName{
_hostName = hostName;
reachability = [Reachability reachabilityWithHostname:hostName.host];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reachabilityChanged:)
name:kReachabilityChangedNotification
object:nil];
[reachability startNotifier];
}
+ (void)stopReachability{
[reachability stopNotifier];
[[NSNotificationCenter defaultCenter]removeObserver:kReachabilityChangedNotification];
}
+(void)reachabilityChanged: (NSNotification *)notification{
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
BOOL isServerCurrentlyReachable = NO;
do{
isServerCurrentlyReachable = [self checkConnectivityToServer];
BOOL wasServerPreviouslyReachable = isServerReachable;
isServerReachable = isServerCurrentlyReachable;
if (NO == wasServerPreviouslyReachable && YES == isServerCurrentlyReachable)
{
NSLog(@"REACHABLE!");
[[NSNotificationCenter defaultCenter]postNotificationName:@"kNetworkReachabilityCustom" object:[NSNumber numberWithBool:YES]];
}
else if (YES == wasServerPreviouslyReachable && NO == isServerCurrentlyReachable)
{
NSLog(@"UNREACHABLE!");
[[NSNotificationCenter defaultCenter]postNotificationName:@"kNetworkReachabilityCustom" object:[NSNumber numberWithBool:NO]];
}
[NSThread sleepForTimeInterval:5.0];
}while(!isServerCurrentlyReachable);
});
}
+(BOOL)checkConnectivityToServer{
NSURLResponse *response;
NSError *error=nil;
NSData *data = nil;
NSURLRequest *request = [NSURLRequest requestWithURL:_hostName];
data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
return (data && response);
}
@end