iOS(ネットワークの接続状態の検出)

iOSでネットワークの接続状態を検出する方法です。
さて, iphoneでネットワークへ接続が確認された場合のみ使用可能の機能とか, ユーザへの親切心でネットワークに接続していなければUIをDisabledにしておくとか,
そういった動作を入れたい場合はネットワークへの接続状態をあらかじめコードで調べる方法が必要です。

幸いなことにAppleさんが, サンプルを提供してくださっているのでこれを利用しない手はありません。

Apple Developer Reachability
Reachability.m, Reachability.h を利用します。

Reachability

Versionの違いで多少の違いはでてくるかもしれません。このReachabilityで公開されているメソッドは以下のようなメソッドです。

Method Description
reachabilityWithHostName ホストへの接続を調べます
reachabilityWithAddress IPアドレスベースの接続を調べます
reachabilityForInternetConnection 3G, LTEなどのPhoneのネットワークを調べます
reachabilityForLocalWiFi Wifi接続を調べます

サンプル1(Reachability)

一回限りの検出をするには, Reachabilityを単独で使います。

Reachability* curReach = [Reachability reachabilityForInternetConnection];
NetworkStatus netStatus = [curReach currentReachabilityStatus];
if (netStatus == NotReachable) {
    // Disconnect
}
else {
    // Connect
}

サンプル2

さらにこれをObserverにしてリアルタイムで監視します。

NetworkObserver.h

extern NSString const * kNETWORKRCONNECT;
extern NSString const * kNETWORKDISCONNECT;

@interface NetworkObserver : NSObject
-(BOOL)startReachability;
@end

NetworkObserver.m

NSString const * kNETWORKRCONNECT = @"Connection";
NSString const * kNETWORKDISCONNECT = @"DisConnection";

@interface NetworkObserver()
@property(nonatomic, readwrite)NSMutableDictionary *observers;
@property(nonatomic, readwrite)Reachability *internetReach;
@property(nonatomic, readwrite)Reachability *wifiReach;
@property(nonatomic, readwrite)BOOL connect;
@end

@implementation NetworkObserver

-(BOOL)startReachability
{
    // Initial setting
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(reachabilityChanged:)
                                                 name: kReachabilityChangedNotification
                                               object: nil];
    
    // 3G
    self.internetReach = [Reachability reachabilityForInternetConnection];
    [self.internetReach startNotifier];
    BOOL res3G = [self updateInterfaceWithReachability: self.internetReach];
    
    // Wifi
    self.wifiReach = [Reachability reachabilityForLocalWiFi];
    [self.wifiReach startNotifier];
    BOOL resWifi = [self updateInterfaceWithReachability: self.wifiReach];
    
    self.connect = res3G || resWifi;
    return res3G || resWifi;
}

-(BOOL) updateInterfaceWithReachability:(Reachability*)curReach
{
    NetworkStatus status = [curReach currentReachabilityStatus];
    if( status == NotReachable )
    {
        // Disconnected
        NSLog(@"Disconnected");
        return NO;
    }
    else
    {
        // 3G, Wifi?
        if(curReach == self.internetReach)
        {
            // 3G
            NSLog(@"3G");
        }
        else if(curReach == self.wifiReach)
        {
            // Wifi
            NSLog(@"Wifi");
        }
        return YES;
    }
}

- (void)reachabilityChanged:(NSNotification*)note
{
    Reachability* curReach = [note object];
    NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
    BOOL res = [self updateInterfaceWithReachability: curReach];
    
    // Resume or Stop
    if ( self.connect != res )
    {
        self.connect = res;
        if ( res )
        {
            // Post new notification
            NSNotification *notification = [NSNotification notificationWithName:(NSString*)kNETWORKRCONNECT object:nil];
            [[NSNotificationCenter defaultCenter] postNotification:notification];
        }
        else
        {
            // Post new notification
            NSNotification *notification = [NSNotification notificationWithName:(NSString*)kNETWORKDISCONNECT object:nil];
            [[NSNotificationCenter defaultCenter] postNotification:notification];
        }
    }
}
@end

このコードは簡単です。ネットワークの状態を調べて, wifi, 3Gどちらかが機能していれば, NSNotificationで結果を流すといったものです。
つながっていなければそれをNotificationで飛ばします。
さらに, これはObserverとして,変化があればそれを通知してくれます。