Thomas Bandt

How To Check Network Reachability With Xamarin.iOS on iOS 8

Some features of your app may only be useful if the device of your user is currently connected to the internet, so you can make API calls, load images or do some other stuff.

Published on Friday, 15 May 2015

Therefore it's convenient to check the availability of an established internet connection, so you can show some warnings or instructions if the device isn't connected.

Thankfully there's a simple solution around for years, see the ReachabilitySample on GitHub. It's using some handy features that are baked-in in iOS. So it's not necessary to ping a server every x seconds, instead the operating system sends notifications about changes regarding the network connection you can subscribe to.

The bad thing is: That doesn't seem to work properly on iOS 8.3 anymore, so I had to do some investigation. At the end of it most of the class was gone, but what was left, is now working.

I won't do a pull-request because I deleted most of the public stuff and instead went for a much simpler API, that only tells if the device is connected or not. But maybe it's useful for someone else, so here it is:

using System;
using System.Net;
using SystemConfiguration;
using CoreFoundation;

public enum NetworkStatus
{
    NotReachable,
    ReachableViaCarrierDataNetwork,
    ReachableViaWiFiNetwork
}

public static class Reachability
{
    private static NetworkReachability _defaultRouteReachability;

    public static event EventHandler ReachabilityChanged;

    public static bool IsNetworkAvailable()
    {
        if (_defaultRouteReachability == null)
        {
            _defaultRouteReachability = new NetworkReachability(new IPAddress(0));
            _defaultRouteReachability.SetNotification(OnChange);
            _defaultRouteReachability.Schedule(CFRunLoop.Current, CFRunLoop.ModeDefault);
        }

        NetworkReachabilityFlags flags;

        return _defaultRouteReachability.TryGetFlags(out flags) &&
            IsReachableWithoutRequiringConnection(flags);
    }

    private static bool IsReachableWithoutRequiringConnection(NetworkReachabilityFlags flags)
    {
        // Is it reachable with the current network configuration?
        bool isReachable = (flags & NetworkReachabilityFlags.Reachable) != 0;

        // Do we need a connection to reach it?
        bool noConnectionRequired = (flags & NetworkReachabilityFlags.ConnectionRequired) == 0;

        // Since the network stack will automatically try to get the WAN up,
        // probe that
        if ((flags & NetworkReachabilityFlags.IsWWAN) != 0)
            noConnectionRequired = true;

        return isReachable && noConnectionRequired;
    }

    private static void OnChange(NetworkReachabilityFlags flags)
    {
        var h = ReachabilityChanged;
        if (h != null)
            h(null, EventArgs.Empty);
    }
}

What do you think? Drop me a line and let me know!