【iPhone SDK】ネットワーク接続チェック

アプリを実行しているとき、
本体がネットワークにつながっているかどうかをチェックしなければならない場合があると思います。

ストリーミングでMPMoviePlayerControllerを使用した動画再生や、ツイッタークライアントソフトなど
通信を行う前に3G回線かWifiにつながっているかを調べる方法を探しました。

キーワードとして「Reachability」を見つけました。

参考サイト:こちら

大容量無制限レンタルサーバー【X2】利用者のみドメインが激安

3GかWifiかという判別は不要だったこともあり、
サンプルコードを見ながら自分で組んでみました。

ヘッダには以下を登録します。

#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
// Notification名
#define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification"

@interface Reachability : NSObject {
 SCNetworkReachabilityRef m_oReachabilityRef;
}


- (id)init;

- (BOOL) checkConnectNetWork;
- (BOOL) startNotifier;
- (void) stopNotifier;
@end


ソースファイルには関数を実装していきます。

/**
 * @brief 初期化
 */
- (id)init {
 if((self = [super init])){
 
  // 構造体作成
  struct sockaddr_in zeroAddress;
  bzero(&zeroAddress, sizeof(zeroAddress));
  zeroAddress.sin_len = sizeof(zeroAddress);
  zeroAddress.sin_family = AF_INET;
  
  m_oReachabilityRef
   = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault
         , (const struct sockaddr*)&zeroAddress);
 }
 return self;
}

/**
 * @brief 解放
 */
- (void)dealloc {

 [super dealloc];
}

/**
 * @brief ネットワーク監視開始
 */
- (BOOL)startNotifier {
 BOOL bRet = NO;
 SCNetworkReachabilityContext context = {0, self, nil, nil, nil};
 
 if(SCNetworkReachabilitySetCallback(m_oReachabilityRef, ReachabilityCallback, &context)){
  if(SCNetworkReachabilityScheduleWithRunLoop(m_oReachabilityRef
      , CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)){
   bRet = YES;
  }
 }
 return bRet;
}

/**
 * @brief ネットワーク監視停止
 */
- (void)stopNotifier {
 if(m_oReachabilityRef){
  SCNetworkReachabilityUnscheduleFromRunLoop(m_oReachabilityRef
   , CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
 }
}

/**
 * @brief ネットワーク接続チェック
 */
- (BOOL) checkConnectNetWork {
 BOOL isConnect = NO;
 if(m_oReachabilityRef){
  SCNetworkReachabilityFlags flags = 0;
  if(SCNetworkReachabilityGetFlags(m_oReachabilityRef, &flags)){
   // 接続有無
   isConnect = (flags & kSCNetworkFlagsReachable);
  }
 }
 return isConnect;
}

ネットワーク監視を開始するときにコールバック関数を登録
/**
 * @brief コールバック関数
 */
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) {
 NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init];
 Reachability* pNoteObject = (Reachability*)info;
 
 [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification
           object: pNoteObject];
 [myPool release];
}

インポートとして以下を忘れずに明記しておきましょう

#import <netinet/in.h>

プロジェクトに既存のフレームワークとして
SystemConfiguration.framework
を追加しましょう



ちなみに「SCNetworkReachabilityFlags」には以下の情報が登録されているようです。

enum {   kSCNetworkReachabilityFlagsTransientConnection = 1<<0
  , kSCNetworkReachabilityFlagsReachable = 1<<1
  , kSCNetworkReachabilityFlagsConnectionRequired = 1<<2
  , kSCNetworkReachabilityFlagsConnectionOnTraffic = 1<<3
  , kSCNetworkReachabilityFlagsInterventionRequired = 1<<4
  , kSCNetworkReachabilityFlagsConnectionOnDemand = 1<<5
  , kSCNetworkReachabilityFlagsIsLocalAddress = 1<<16
  , kSCNetworkReachabilityFlagsIsDirect = 1<<17
  , kSCNetworkReachabilityFlagsIsWWAN = 1<<18
  , kSCNetworkReachabilityFlagsConnectionAutomatic = kSCNetworkReachabilityFlagsConnectionOnTraffic
};

よくわからない場合、気にしなくていいです。




使い方は簡単です。
チェックしたい画面のソースにて
self.m_pReachability = [[Reachability alloc] init];
// 現在のネットワーク状況を取得
 m_bConnectNetWork = [m_pReachability checkConnectNetWork];
// ネットワーク状況を監視開始
 [m_pReachability startNotifier];
// ネットワーク状況が変化した場合、イベント発生
 [[NSNotificationCenter defaultCenter] addObserver:self
           selector:@selector(reachabilityChanged:)
           name:kReachabilityChangedNotification
           object: nil];


m_bConnectNetWork はBOOL型のメンバ変数です。
Reachabilityクラス生成時に現在のネットワーク状況を取得しているだけです。

ネットワーク監視を開始し、NSNotificationCenterにてネットワーク状況が変化したらイベント取得できるように登録します。

ネットワーク状況が変化したらっということはオフラインになったかオンラインになったかの2択しか基本発生しません。
なので、生成時にネットワーク状況を取得しておかないと、オンラインの場合、またはオフラインの場合イベントが発生しません。

そのためbConnectNetWork が初期値から変化しないということになります。

/**
 * @brief ネットワークが変化した場合、呼ばれる
 */
- (void) reachabilityChanged: (NSNotification* )notification
{
 // ネットワーク状況を更新
 m_bConnectNetWork = [m_pReachability checkConnectNetWork];
}

というわけでネットワーク状況が変化したときに、改めてネットワーク状況を取得することで
m_bConnectNetWork の値が書き換わるという仕組みです。

あとは通信処理を行う前にm_bConnectNetWork の値をチェックして、
アラートを表示するなりといった分岐をかけることが可能です。

サンプルから抜粋してネットワーク状況チェックのみに絞った機能にしたので、
3G、Wifiの判別まで行いたい場合は、サンプルソースをじっくり参照して組み込んでください。

まぁ、サンプルクラスをそのまま使えばいい話なんですが(爆


パソコンを売りたい方

この記事へのコメント


この記事へのトラックバック