ネットを利用するiPhoneアプリケーションは、圏外の通知が必須に? - 24/7 twenty-four seven
上記の記事で書いたように、現在、ネットを使用するアプリケーションは、ネットワークに接続できないときには、何らかの形でユーザーに知らせないといけないので、僕が「はてな touch」「LDR touch」「テレビ番組表」でやっている方法を書きます。
Reachability
iOS Dev Center - Apple DeveloperにサンプルコードとしてアップルがReachabilityというものを公開しています。
こちらを使うと、ネットワークの状態を簡単に取得することができます。
また、圏外になったときに自動的に通知してくれる機能もついています。
使い方
ReachabilityのプロジェクトからReachability.hとReachability.mをコピーします。
SystemConfiguration.frameworkを追加します。
接続確認のために接続先のアドレスを設定します。
Reachabilityオブジェクトはシングルトンなので、アプリケーションで一度だけ行えばOKです。
[[Reachability sharedReachability] setHostName:@"reader.livedoor.com"];
アップルのサンプルコードのように、applicationDidFinishLaunching:メソッドで初期設定をして、ネットワークの状態を確認するメソッドをコントローラに実装するのが分かりやすいと思います。
- (void)updateStatus { self.remoteHostStatus = [[Reachability sharedReachability] remoteHostStatus]; self.internetConnectionStatus = [[Reachability sharedReachability] internetConnectionStatus]; self.localWiFiConnectionStatus = [[Reachability sharedReachability] localWiFiConnectionStatus]; } - (void)applicationDidFinishLaunching:(UIApplication *)application { [[Reachability sharedReachability] setHostName:@"reader.livedoor.com"]; [self updateStatus];
ネットワークの状態は以下の3種類があります。
typedef enum { NotReachable = 0, ReachableViaCarrierDataNetwork, ReachableViaWiFiNetwork } NetworkStatus;
- NotReachable
- ホスト(接続先)に繋がらない
- ReachableViaCarrierDataNetwork
- 3Gネットワークを使って接続できる
- ReachableViaWiFiNetwork
- WiFiで接続できる
Reachabilityオブジェクトの各プロパティは、それぞれ上記の3種類の状態をとります。
状況に応じて使い分けます。
- remoteHostStatus
- リモートホスト(設定した接続先)に繋がるかどうか
- internetConnectionStatus
- インターネットに繋がるかどうか
- localWiFiConnectionStatus
- ローカルなWi-Fiネットワークに繋がるかどうか(Bonjourの機器など)
例えば以下では、「インターネットに接続できない」「3Gで接続している」「Wi-Fiで接続している」の3種類を判定しています。
if ([[Reachability sharedReachability] internetConnectionStatus] == NotReachable) { NSLog(@"Access Not Available."); } else if ([[Reachability sharedReachability] internetConnectionStatus] == ReachableViaCarrierDataNetwork) { NSLog(@"Available Via Carrier Data Network."); } else if ([[Reachability sharedReachability] internetConnectionStatus] == ReachableViaWiFiNetwork) { NSLog(@"Available Via WiFi Network."); }
圏外を通知する
たいていのアプリケーションは、接続先は決まっているでしょうから、「リモートホストに繋がるかどうか」だけ判定すればいいと思います。
if ([[Reachability sharedReachability] remoteHostStatus] == NotReachable) {
以下のコードは、データを取得する前に判定をし、接続できない場合はアラートで通知する例です。
- (void)refleshIfNeeded { if ([[Reachability sharedReachability] remoteHostStatus] == NotReachable) { NSBundle *bundle = [NSBundle mainBundle]; NSDictionary *infoDictionary = [bundle localizedInfoDictionary]; NSString *appName = [[infoDictionary count] ? infoDictionary : [bundle infoDictionary] objectForKey:@"CFBundleDisplayName"]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:appName message:NSLocalizedString(@"NotReachable", nil) delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; [alert release]; return; } [hotEntryView reloadData]; }
Tips
networkStatusNotificationsEnabledプロパティをYESに設定すると、ネットワークの状態が変化したときに、通知を受け取れます。
[[Reachability sharedReachability] setNetworkStatusNotificationsEnabled:YES];
上記の設定をした上で、状態変化の通知を受け取るオブジェクトと、通知を受けたときに呼び出されるメソッドを登録します。
ここで登録したオブジェクトは、解放される前に、自分で登録解除する必要があります。
- (void)viewDidLoad { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:@"kNetworkReachabilityChangedNotification" object:nil]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [super dealloc]; }
「LDR touch」ではオフラインでもダウンロード済みのデータを閲覧することができるので、アラートは出さずに画面の色を変えることで、オフライン状態が分かるようにしています。
どの画面を表示しているときでも同様に処理できるように、通知の仕組みを使っています。
- (void)reachabilityChanged:(NSNotification *)note { LoginManager *loginManager = [LDRTouchAppDelegate sharedLoginManager]; if (loginManager.remoteHostStatus == NotReachable) { [refleshButton setEnabled:NO]; [pinListButton setEnabled:NO]; [toolBar setBarStyle:UIBarStyleBlackOpaque]; } else { [refleshButton setEnabled:YES]; [pinListButton setEnabled:YES]; [toolBar setBarStyle:UIBarStyleDefault]; } }