This will be a pretty quick and simple tutorial on having your app check for connectivity. This is one thing that Apple wants from your app, and one thing they’ll check for and possibly reject it for if it isn’t in there. You should add code to check for connectivity in your app if there is anything in it at all that needs to connect to the outside world.

1.) Create a Tab Bar Application and name it ConnectivityTutorial.
2.) Before we do anything else we need add a class to our project. It is the Reachability class and I got it straight from Apple’s Reachability sample application.
http://developer.apple.com/library/ios/#samplecode/Reachability/Introduction/Intro.html
Reachability.h
#import#import typedef enum { NotReachable = 0, ReachableViaWiFi, ReachableViaWWAN } NetworkStatus; #define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification" @interface Reachability: NSObject { BOOL localWiFiRef; SCNetworkReachabilityRef reachabilityRef; } //reachabilityWithAddress- Use to check the reachability of a particular IP address. + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; //reachabilityForInternetConnection- checks whether the default route is available. // Should be used by applications that do not connect to a particular host + (Reachability*) reachabilityForInternetConnection; //reachabilityForLocalWiFi- checks whether a local wifi connection is available. + (Reachability*) reachabilityForLocalWiFi; //Start listening for reachability notifications on the current run loop - (BOOL) startNotifier; - (void) stopNotifier; - (NetworkStatus) currentReachabilityStatus; //WWAN may be available, but not active until a connection has been established. //WiFi may require a connection for VPN on Demand. - (BOOL) connectionRequired; @end
Reachability.m
#import#import #import #import #import #import #import #import "Reachability.h" @implementation Reachability static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info) { // NSLog(@"ReachabilityCallback"); #pragma unused (target, flags) NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback"); NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback"); //We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively // in case someone uses the Reachablity object in a different thread. NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init]; Reachability *noteObject = (Reachability *) info; // Post a notification to notify the client that the network reachability changed. [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject]; [myPool release]; } - (BOOL) startNotifier { BOOL retVal = NO; SCNetworkReachabilityContext context = {0, self, NULL, NULL, NULL}; if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)) { if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) { retVal = YES; } } return retVal; } - (void) stopNotifier { if(reachabilityRef!= NULL) { SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); } } + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); Reachability* retVal = NULL; if(reachability!= NULL) { retVal= [[[self alloc] init] autorelease]; if(retVal!= NULL) { retVal->reachabilityRef = reachability; retVal->localWiFiRef = NO; } } return retVal; } + (Reachability*) reachabilityForInternetConnection; { struct sockaddr_in zeroAddress; bzero(&zeroAddress, sizeof(zeroAddress)); zeroAddress.sin_len = sizeof(zeroAddress); zeroAddress.sin_family = AF_INET; return [self reachabilityWithAddress: &zeroAddress]; } + (Reachability*) reachabilityForLocalWiFi; { struct sockaddr_in localWifiAddress; bzero(&localWifiAddress, sizeof(localWifiAddress)); localWifiAddress.sin_len = sizeof(localWifiAddress); localWifiAddress.sin_family = AF_INET; // IN_LINKLOCALNETNUM is defined in as 169.254.0.0 localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress]; if(retVal!= NULL) { retVal->localWiFiRef = YES; } return retVal; } #pragma mark Network Flag Handling - (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags { BOOL retVal = NotReachable; if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect)) { retVal = ReachableViaWiFi; } return retVal; } - (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags { if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) { // if target host is not reachable return NotReachable; } BOOL retVal = NotReachable; if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) { // if target host is reachable and no connection is required // then we'll assume (for now) that your on Wi-Fi retVal = ReachableViaWiFi; } if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) { // ... and the connection is on-demand (or on-traffic) if the // calling application is using the CFSocketStream or higher APIs if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) { // ... and no [user] intervention is needed retVal = ReachableViaWiFi; } } if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) { // ... but WWAN connections are OK if the calling application // is using the CFNetwork (CFSocketStream?) APIs. retVal = ReachableViaWWAN; } return retVal; } - (BOOL) connectionRequired; { NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef"); SCNetworkReachabilityFlags flags; if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) { return (flags & kSCNetworkReachabilityFlagsConnectionRequired); } return NO; } - (NetworkStatus) currentReachabilityStatus { NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef"); NetworkStatus retVal = NotReachable; SCNetworkReachabilityFlags flags; if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) { if(localWiFiRef) { retVal = [self localWiFiStatusForFlags: flags]; } else { retVal = [self networkStatusForFlags: flags]; } } return retVal; } - (void) dealloc { [self stopNotifier]; if(reachabilityRef!= NULL) { CFRelease(reachabilityRef); } [super dealloc]; } @end
Just go ahead and add those files to the project. You can do this by adding a new file that is a subclass of NSObject and then copy and paste the above to the respective files.
This Reachability class uses the SystemConfiguration.framework, so you’ll need to add that to the project.
3.) We don’t need to do anything to the user interface. We’ll just be working in the app delegate files. First open up the app delegate header file. We’re going to add the Reachability class using the @class directive.
@class Reachability;
All this does is tell the compiler that Reachability is in fact a class. We won’t import Reachability until the implementation file when we actually referenced.
Then we’ll create an iVar of the Reachability class.
Reachability *internetReach;
That’s it for the header file, here’s what the full file looks like.
#import@class Reachability; @interface ConnectivityTutorialAppDelegate : NSObject { Reachability *internetReach; } @property (nonatomic, retain) IBOutlet UIWindow *window; @property (nonatomic, retain) IBOutlet UITabBarController *tabBarController; @end
4.) Now we’ll open the implementation file. Here we will need to import the Reachability class.
#import "ConnectivityTutorialAppDelegate.h" #import "Reachability.h"
The rest of our work will be done in the applicationDidBecomeActive method.
5.) First we’ll implement our iVars.
internetReach = [[Reachability reachabilityForInternetConnection] retain];
[internetReach startNotifier];
6.) Then we’ll set the NetworkStatus variable created in Reachability.
NetworkStatus netStatus = [internetReach currentReachabilityStatus];
7.) And finally we’ll use the netStatus in a switch block.
switch (netStatus)
{
case ReachableViaWWAN:
{
break;
}
case ReachableViaWiFi:
{
break;
}
case NotReachable:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"We are unable to make a internet connection at this time. Some functionality will be limited until a connection is made." delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
[alert release];
break;
}
}
8.) That handles the check when the app becomes active. We can also add a notification for when ever the reachability changes. Just add this line to the didFinishLaunchingWithOptions method in the app delegate.
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(reachabilityChanged:) name: kReachabilityChangedNotification object: nil];
And then add the reachability method to the same file.
//Called by Reachability whenever status changes.
- (void) reachabilityChanged: (NSNotification* )note
{
Reachability* curReach = [note object];
NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
NetworkStatus netStatus = [curReach currentReachabilityStatus];
switch (netStatus)
{
case ReachableViaWWAN:
{
break;
}
case ReachableViaWiFi:
{
break;
}
case NotReachable:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"We are unable to make a internet connection at this time. Some functionality will be limited until a connection is made." delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
[alert release];
break;
}
}
}
It can become annoying to send a message overtime the reachability changes if you are going in and out of service, so you can decide how you want to handle this.
8.) Now how do we test this? If you are testing in the simulator you’ll need to disconnect the computer from the internet to test for a failure to connect. If you are using wifi, just turn Airport off.
9.) That’s it. We put this code in our app delegate to check for connectivity when the app becomes active. You could also add this to individual views, for example you could add it to a view controller that displays a UIWebView, or to one that might use a web service. Then of course you can handle the result however you wish.

hi, i was having problems with the Reachability class and ARC but i found that somebody just port the class to iOS5 heres the link https://gist.github.com/1182373
everything else works just as you write it =)!! cheers!!
hi kent,are you busy ? data with many pretty lady and forgot you blog ? anyway,you didn’t update your blog for a long time.everytime i came here,nothing new.i am a little disapointment.come on ! i am looking forward to read your article !
Yes I have been busy. But it’s a new job that is the reason. Still getting settled in and then with the holiday season I just haven’t had time for the blog, which I actually feel really guilty about. I’m hoping to get back on a regular schedule after the new year.
Hi Kent
Can you help me in making a scroll view
like we see on IMDB Iphone application
scrolling different movies with right and left swap.
regards
Dinesh Kaushik
@dineshkaushik18
Dear you can easily use the picker View Comtroller the tutorial of ehich can be easily found, the 1 I used is http://thenewboston.org/list.php?cat=28, #31 single picker, It worked great, you cannot implement a drop down like spinners in android
Hope it helps
Regards
Aleem
Hey sir, can you make a tutorial on youtube showing step by step how to do this. If the person is not connected to the internet a pop up error comes up please!?! Send me a link if you can. Im new at Xcode, and this is one of the best so far but I need it in video form I don’t understand written that much. . Thank you!
In the app delegate method applicationDidBecomeActive are these two lines of code:
internetReach = [[Reachability reachabilityForInternetConnection] retain];
[internetReach startNotifier];
That means each time the app is moved from the background to the foreground a new Reachibility object is retained without releasing the current Reachibility object. Is that intentional? Seems like a memory leak…
Good easy to follow tutorial. Made what was an annoying topic very simple! Thanks.
Hi,
This was a nice article. I am looking for some inputs into connecting to a wireless network programatically from an app on iOS 6 by passing in a SSID and the pass word. Is this possible? Any suggestions would be of great help.
Cheers