Héctor Ramos

Drop in Reachability Check

Every iOS application that requires an Internet connection should make use of the Apple Reachability classes. These allow you to easily check if there is a WAN connection available and/or if a specific host can be reached.

You never know when your application will run in Airport mode or in a dead area with no cell connection at all. Furthermore, the user might not have 3G service but might be connected through a Wi-Fi hotspot. Perhaps in a future OS update, an additional WAN connection might become available through Bluetooth or a completely new protocol. For these reasons, I can’t advise you to create your own Reachability code, when Apple’s will suffice: you only care if there is access to a WAN, or at the very least, if Host X is reachable (who cares about the pathway to it?).

In iPhone OS 2, the Reachability classes were kind of obscure, hidden away in the Apple Sample Code and with no easy way of dropping them in to a project. By default they were synchronous and would need some modification to work properly asynchronously - I don’t really remember the details, I just remember I had to do this a couple of times and it was very annoying. So I was very happy to find this answer in Stack Overflow which provides a step by step to use the updated Reachability classes along with NSNotifications to asynchronously determine reachability.

You should always visit Stack Overflow to get the latest code and comments, but I’m saving a local copy here for posterity:

An updated answer:

1) Add SystemConfiguration framework to the project but don’t worry about including it anywhere

2) Add Reachability.h and Reachability.m to the project

3) Add @class Reachability; to the .h file of where you are implementing the code

4) Create a couple instances to check in the interface section of the .h file:

Reachability* internetReachable;
Reachability* hostReachable;

5) Add a method in the .h for when the network status updates:

- (void)checkNetworkStatus:(NSNotification *)notice;

6) Add #import "Reachability.h" to the .m file where you are implementing the check

7) In the .m file of where you are implementing the check, you can place this in one of the first methods called ( init or viewWillAppear or viewDidLoad, etc.):

- (void)viewWillAppear:(BOOL)animated {
  // check for internet connection
  [[NSNotificationCenter defaultCenter] 
    addObserver:self 
    selector:@selector(checkNetworkStatus:) 
    name:kReachabilityChangedNotification 
    object:nil];

  internetReachable = [[Reachability reachabilityForInternetConnection] retain];
  [internetReachable startNotifier];

  // check if a pathway to your host exists
  hostReachable = [[Reachability reachabilityWithHostName: @"www.hectorramos.com"] retain];
  [hostReachable startNotifier];

  // now patiently wait for the notification
}

8) Set up the method for when the notification gets sent and set whatever checks or call whatever methods you may have set up (in my case, I just set a BOOL)

// called after network status changes
- (void)checkNetworkStatus:(NSNotification *)notice {

  NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
 
  switch (internetStatus) {
    case NotReachable: {
      NSLog(@"The internet is down.");
      self.internetActive = NO;
      break;
    }
    case ReachableViaWiFi: {
      NSLog(@"The internet is working via WIFI.");
      self.internetActive = YES;
      break;
    }
    case ReachableViaWWAN: {
      NSLog(@"The internet is working via WWAN.");
      self.internetActive = YES;
      break;
    }
  }

  NetworkStatus hostStatus = [hostReachable currentReachabilityStatus];
  
  switch (hostStatus) {
    case NotReachable: {
      NSLog(@"A gateway to the host server is down.");
      self.hostActive = NO;
      break;
    }
    case ReachableViaWiFi: {
      NSLog(@"A gateway to the host server is working via WIFI.");
      self.hostActive = YES;
      break;
    }
    case ReachableViaWWAN: {
      NSLog(@"A gateway to the host server is working via WWAN.");
      self.hostActive = YES;
      break;
    }
  }
}

9) In your dealloc or viewWillDisappear or similar method, remove yourself as an observer

- (void)viewWillDisappear:(BOOL)animated {
  [[NSNotificationCenter defaultCenter] removeObserver:self];
}

Note: There might be an instance using viewWillDisappear where you receive a memory warning and the observer never gets unregistered so you should account for that as well.