Reachability with blocks for everyday use

As I developed a web service and the matching iOS client, I arrived at a point where I wanted to wrap every request I send into a wrapper incorporating hostname reachability with blocks on success/error or simply on completition.

Reachability with blocks for everyday use

Reachability should be this simple, free from notifications, run loops, any weird stuff.

go using eppz!reachability at

I tried to test it on my local server, which I can reach over a local/private/non-routable IP address from test devices. But as it turned out (after days of struggling with numerous third-praty Reachability implementations) Reachability won’t ever call back when I pass in an IP address as input, at least with my network setup (which is like every network setup as far as I know). The discussion of this issue is dispatched on a separate thread at Why asynchronous SCNetworkReachability not works with IP addresses?.

Preliminaries leading to rewrite reachability with blocks

All in all, I decided to dig deeper into Apple’s sample code (and documentation) and understand all those seemingly weird things, then get rid of the most. In the end I found that asking for a host Reachability is actually three lines of code.

SCNetworkReachabilityRef reachabilityRef = SCNetworkReachabilityCreateWithName(NULL, [@"google.com" UTF8String]);
SCNetworkReachabilityFlags reachabilityFlags;
SCNetworkReachabilityGetFlags(reachabilityRef, &reachabilityFlags);

No more. Three innocent lines of code. No notifications (which I instinctively don’t like), no run loops, no any weird stuff, like external setting an objects instance variables. Just the pure feature. The sample above uses a synchronous call I found in SCNetworkReachabiliy documentation called SCNetworkReachabilityGetFlags (see documentation).

Of course you need to import <SystemConfiguration/SystemConfiguration.h> framework where these functions live. The official code has some mention on encourage the async implementation (with the callback function and runLoop scheduling) since in some cases network communication can reach over 30 seconds, and blocking the main thread for such a duration leads to terminate the application by the OS.

Anyway, blocking the main thread even for a second is not too user friendly, so it is fairly understandable (this convienced me to implement reachability with blocks actually instead of using simply the synchronous way). Also when you want to constantly listen for network changes, you cannot use the sync solution above. Actually the async method is also really a few lines of code.

static void reachabilityCallback(SCNetworkReachabilityRef reachabilityRef, SCNetworkReachabilityFlags flags, void* info)
{
    RCViewController *viewController = (__bridge RCViewController*)info; //Cast context object.
    [viewController showReachabilityFlags:flags]; //Show.

    //Tear down reachability.
    SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
    CFRelease(reachabilityRef);
}

-(void)reach:(NSString*) hostName
{
    //Create with context.
    SCNetworkReachabilityRef reachabilityRef = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
    SCNetworkReachabilityContext context = {0, (__bridge void*)self, nil, nil, nil};

    if (NO) //The synchronous way.
    {
        //Get flags.
        SCNetworkReachabilityFlags flags;
        SCNetworkReachabilityGetFlags(reachabilityRef, &flags);

        [self showReachabilityFlags:flags]; //Show.
    }

    else //The asynchronous way.
    {
        //Set callback, then register.
        SCNetworkReachabilitySetCallback(reachabilityRef, reachabilityCallback, &context);
        SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
    }
}

You can see how to hook up the C callback with Objective-C code using a reference to the viewController as a context of reachability. So this method also free of any notification, and is as Cocoa as it can.

Knowing this it is really a pleasure to wrap it to a class that fits some usual use-cases, like a block based on-demand reachability test, and a reachability listener with a delegate connection.

Reachability with blocks for everyday use

I did implement such a wrapper (with a workaround aiming the IP address issue), so if you need a drop-in “reachability with blocks” class grab eppz!reachability at GitHub. The client code for this is really a one-liner.

//Get status on-demand.
[EPPZReachability reachHost:@"eppz.eu" completition:^(EPPZReachability *reachability)
{ if (reachability.reachable) [self postSomething]; }];

For constantly listening reachability, I kept a delegate-based imlementation, again, with the lowest possible impact on controller code.

//Listen.
[EPPZReachability listenHost:hostNameOrIPaddress delegate:self];

//Get notified.
-(void)reachabilityChanged:(EPPZReachability*) reachability
{ if (reachability.reachableViaCellular) [self skipThumbnails]; }

You can inspect it in action in the testbed project along it’s really thin controller implementation.

Testbed for eppz!reachability (implementing reachability with blocks).

You can play around with both synchronous and asynchronous way of reachability, watch the network come and go, or get closer to the lower level flags if you feel explorous to.

See RCReachabilityClientViewController.m at

I can think of a category on this with some more convenient factory methods with separate blocks for every outcome to spare that if statement in completition, but the main point was here is the block-based manner.

DISCLAIMER. THE INFORMATION ON THIS BLOG (INCLUDING BUT NOT LIMITED TO ARTICLES, IMAGES, CODE SNIPPETS, SOURCE CODES, EXAMPLE PROJECTS, ETC.) IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE INFORMATION ON THIS BLOG (INCLUDING BUT NOT LIMITED TO ARTICLES, IMAGES, CODE SNIPPETS, SOURCE CODES, EXAMPLE PROJECTS, ETC.).

  • Friend, im from chile so my english it’s a little rusty…

    let me explain to you… i need to develop an app and it sound very simple but right now im kinda messed up with code… i need to find out if im on internet open an url https://blablabla…. but if im on intranet (vpn and stuff) open the same url but with http://blablabla protocol… without the “S”, can you help me please

    right now i was trying to use the scnetworkreachabilitycreatewithname but the flags just works with hostnames and not with IP address… i was thinking that maybe… i can check out a valid ip address to check if its conected to the vpn… and if its not valid then open the other url
    if you have another idea please let me know!!!!! tnks