iPhone Network Connectivity Test Example


Every iPhone developer that has integrated a network connection based application has had to follow the Apple HID (Human Interface Design) rules. This means, that in order to get the Apple reviewers to sign-off on your application, you have to pass the network connectivity test. Basically, in the case of a catastrophic network disconnect issue with 3G and WiFi does your application properly alert the user that it will not perform properly without the usage of the network? I’ve seen a lot of workaround techniques where users attempt to do an HTTP GET on say Google or some other website. Clearly, this kind of technique will work sporadically in an unknown environment common to the mobile device. I mean, imagine causing your application users to sit through a 5-30 second web request timeout. The end-user will probably believe that the application is hung. The ideal solution happens to be handed to us in the API Framework SCNetworkReachability. (Make sure your codebase is linked properly with the “SystemConfiguration” Framework).
It’s worked for me and I recommend it for doing a simple network connectivity test.

#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#import <netdb.h>
#import <SystemConfiguration/SCNetworkReachability.h>
//Snip, you know we're in the implementation...
- (BOOL) connectedToNetwork
{
	// Create zero addy
	struct sockaddr_in zeroAddress;
	bzero(&zeroAddress, sizeof(zeroAddress));
	zeroAddress.sin_len = sizeof(zeroAddress);
	zeroAddress.sin_family = AF_INET;
 
	// Recover reachability flags
	SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
	SCNetworkReachabilityFlags flags;
 
	BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
	CFRelease(defaultRouteReachability);
 
	if (!didRetrieveFlags)
	{
		return NO;
	}
 
	BOOL isReachable = flags & kSCNetworkFlagsReachable;
	BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
	return (isReachable && !needsConnection) ? YES : NO;
}
 
//call like:
-(void) start {
	if (![self connectedToNetwork]) {
                UIAlertView *alert = [[UIAlertView alloc] 
                         initWithTitle:@"Network Connection Error" 
                         message:@"You need to be connected to the internet to use this feature." 
                         delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
		[alert show];
		[alert release];
        } else {
             //do something 
        }
}

This code can also be found on this forum post.

, , , ,

  1. #1 by caio1982 on August 1st, 2009

    Simple and effective (at least on my small scenarios), thanks for sharing such solution 🙂

  2. #2 by momeks on August 8th, 2009

    hi plz put the sample code of this tutorial 🙁

  3. #3 by Chris Danielson on August 11th, 2009

    momeks :

    hi plz put the sample code of this tutorial :(

    Momeks, the code is shown above. That is all that I can give to you right now. It is up to you to play around with and implement effectively a working solution.

  4. #4 by Alessandro on September 28th, 2009

    Cool solution! Did you find a way to understand if the data connection is over 3G or GSM/EDGE?

  5. #5 by Kristin on February 1st, 2010

    Hi — thanks so much for this posting! I have this working in my app now, and I understand about 95% of what’s going on. What I’m not getting is what you’re doing in regards to the first for #imports — could you explain those? Are they all required?

    I have them all added included in my .m file, but I notice that if I comment some of them out, the code still works without error?

    Anyway, if you could provide some details on what’s going on with them, it’d be much appreciated!

    Thanks,
    Kristin.

  6. #6 by Chris Danielson on February 2nd, 2010

    Kristin,
    The only two headers you’ll need for the Network Connection test to be functional are:

    #import <netdb.h>
    #import <SystemConfiguration/SCNetworkReachability.h>

    I left the other ones in there due to the product I was working on before.

    Regards,
    Chris

  7. #7 by Scott on May 14th, 2010

    Will your example above work for a 3g connection?

  8. #8 by Chris Danielson on May 14th, 2010

    Yes, this works for both 3G and WiFi connections.

  9. #9 by patrick m lim on May 17th, 2010

    Hi Chris,

    I’m pretty new to iPhone app development especially Cocoa and Obj C. I have an application where I need to detect wifi access points (minimum of 2 APs). Does the SCNetworkReachability framework allow me to do that?

    Thanks for clearing my doubts!

    Warmest Regards
    Patrick

  10. #10 by Chris Danielson on May 26th, 2010

    Patrick,
    I don’t think the SCNetworkReachability will handle enumerating through the known access points. I did a quick check here, and didn’t see anything.
    Wish I could help you more on this endeavor. Good luck!
    -Chris

  11. #11 by waleed on September 21st, 2010

    his great but its not woking for me

    am getting

    “_SCNetworkReachabilityGetFlags”, referenced from:
    -[TestViewController connectedToNetwork] in TestViewController.o
    “_SCNetworkReachabilityCreateWithAddress”, referenced from:
    -[TestViewController connectedToNetwork] in TestViewController.o
    ld: symbol(s) not found
    collect2: ld returned 1 exit status

  12. #12 by Andrew Hoyer on February 25th, 2011

    Waleed, you need to include these at the top:

    #import
    #import

  13. #13 by Brian on May 16th, 2011

    Should you put this on all pages that make a URL call?

  14. #14 by Chris Danielson on May 16th, 2011

    Brian,
    Ideally, you would avoid redundantly putting this code in every page and access either a static method or an instance method on a particular object.

  15. #15 by Hamon Raphaël on December 5th, 2011

    Hi !

    It seems great, but I’ve found an issue. With some wifi hotspots, the iphone is connected to the hotspot but not logged into the hotspot system but the iphone stays “connected” to the hotspot but doesn’t have internet access. And so, this test doesn’t work for that kind of situation.

    Raphaël

  16. #16 by Chris Danielson on December 7th, 2011

    The fix for what you are asking is to actually try and pull say http://google.com in your initial request. I hate pinging Apple or Google in my tests, but it is in fact a more complete implementation. You can find a great method that does this in the AppiRater source code located at:
    https://github.com/arashpayan/appirater
    - (BOOL)connectedToNetwork {
    // Create zero addy
    struct sockaddr_in zeroAddress;
    bzero(&zeroAddress, sizeof(zeroAddress));
    zeroAddress.sin_len = sizeof(zeroAddress);
    zeroAddress.sin_family = AF_INET;

    // Recover reachability flags
    SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
    SCNetworkReachabilityFlags flags;

    BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
    CFRelease(defaultRouteReachability);

    if (!didRetrieveFlags)
    {
    NSLog(@"Error. Could not recover network reachability flags");
    return NO;
    }

    BOOL isReachable = flags & kSCNetworkFlagsReachable;
    BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
    BOOL nonWiFi = flags & kSCNetworkReachabilityFlagsTransientConnection;

    NSURL *testURL = [NSURL URLWithString:@"http://www.apple.com/"];
    NSURLRequest *testRequest = [NSURLRequest requestWithURL:testURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];
    NSURLConnection *testConnection = [[NSURLConnection alloc] initWithRequest:testRequest delegate:self];

    return ((isReachable && !needsConnection) || nonWiFi) ? (testConnection ? YES : NO) : NO;
    }

    Kind Regards,
    Chris

  17. #17 by Isuru on November 25th, 2014

    I converted this class to Swift. I posted it up on my Github here – https://github.com/Isuru-Nanayakkara/Swift-Reachability

(will not be published)


  1. No trackbacks yet.