I am trying to setup Reachability to show an Alert View when a connection to the internet is lost.
I am struggling to understand how reachability actually works. I have read the documentation and setup the Sample App to review from Apple, but I would like to better understand the code and how it is working.
Within my setup I am looking for two things: 1. Tell me when connection to the internet is lost 2. Tell me when connection to a host address is lost
The code is setup within my Application Delegate as I would like the UIAlertView to appear at anypoint within the application when the connection is lost.
For scenario 1, I am looking to display a UIAlertView to message the user saying the connection is lost. There will be a 'Try Again' button when clicked should then Test the connection again to see if the internet connection has returned if not display the alert view again.
Code: App Delegate imp file:
//Called by Reachability whenever status changes.
- (void)reachabilityChanged:(NSNotification* )note {
Reachability *curReach = (Reachability *)[note object];
NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
NSLog(@"Reachability changed: %@", curReach);
networkStatus = [curReach currentReachabilityStatus];
if (networkStatus == NotReachable) {
NSLog(@"NOT REACHABLE");\
UIAlertView *connectionNotReachable = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"connectionNotReachableTitle", @"Title for alert view - connection Not Reachable") message:NSLocalizedString(@"connectionNotReachableMessage", @"Message for alert view - connection Not Reachable") delegate:self cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(@"connectionNotReachableTryAgain", @"Try again button for alert view - connection Not Reachable"), nil];
[connectionNotReachable show];
return;
} else {
NSLog(@"REACHABLE");
}
}
- (void)monitorReachability {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:ReachabilityChangedNotification object:nil];
self.hostReach = [Reachability reachabilityWithHostName: @"api.parse.com"];
[self.hostReach startNotifier];
self.internetReach = [Reachability reachabilityForInternetConnection];
[self.internetReach startNotifier];
}
Confusion: What I do not understand is how this code actually works. So within my application didFinishLaunchingWithOptions:
I call [self monitorReachability]
.
I guess this setups the notifiers for the hostReach and internetReach. But then within the reachabilityChanged
method how do I determine the difference between if this is hostReach == NotReachable or internetReach == Not Reachable.
Ideally for the hostReach not reachable, I do not want to do much at the moment as this could be that this particular api is not reachable at that time. So I do not want to completely make the app inaccessible during that time.
Your application will be listening to kReachabilityChangedNotification
& prompt you whenever status of network changes.
Your register for notification like this
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityHasChanged:) name:kReachabilityChangedNotification object:nil];
self.internetReachable = [[Reachability reachabilityForInternetConnection] retain];
[self.internetReachable startNotifier];
// check if a host is reachable
self.hostReachable= [Reachability reachabilityWithHostname:@"www.google.com"];
[self.hostReachable startNotifier];
Basically you could set a global flag e.g BOOL isReachable
inside the switch cases and update according to the status of the network reachability status. in your application wherever you are, you could check the global flag if(!isReachable)
then show the alert
-(void) reachabilityHasChanged:(NSNotification *)notice
{
// called after network status changes
NetworkStatus internetStatus = [self.internetReachable currentReachabilityStatus];
switch (internetStatus)
{
case NotReachable:
{
UIAlertView *alert =[[UIAlertView alloc]initWithTitle:@"Errot" message:@"internet not reachable" delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];
[alert show];
isReachable=NO;
break;
}
case ReachableViaWiFi:
{
NSLog(@"The internet is working via WIFI.");
UIAlertView *alert =[[UIAlertView alloc]initWithTitle:@"Info" message:@"WIFI reachable" delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];
[alert show];
isReachable=YES;
break;
}
case ReachableViaWWAN:
{
NSLog(@"The internet is working via WWAN.");
UIAlertView *alert =[[UIAlertView alloc]initWithTitle:@"Info" message:@"WWAN/3G" delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];
[alert show];
isReachable=YES;
break;
}
}
NetworkStatus hostStatus = [self.hostReachable currentReachabilityStatus];
switch (hostStatus)
{
case ReachableViaWWAN:
{
//NSLog(@"3G");
hostActive=YES;
break;
}
case ReachableViaWiFi:
{
// NSLog(@"WIFI");
hostActive=YES;
break;
}
case NotReachable:
{
hostActive=NO;
break;
}
}
}
If you are facing problems in getting started with Reachability then just download the sample code for Reachability.
If you have a look at the method reachabilityForInternetConnection
in Reachability
class then you would find out that it is checking for internet connection generally, without focusing on a particular host, it only checks if internet gateway is reachable or not.
+ (Reachability*) reachabilityForInternetConnection;
{
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
return [self reachabilityWithAddress: &zeroAddress];
}