iOSアプリで、ネットワークに接続するには標準SDKのNSURLConnectionやNSURLSessionを使った通信はもちろんのこと、AFNetworkingをはじめとする便利なライブラリもあって本当に簡単に実現できます。
サーバサイドも、自前で準備してPHPなどでAPIを用意しなくてもParseみたいなmBaaSを利用するとあっという間に完成してしまいます。
本当に助かります、便利な世の中ですね。
で、結局ネットワークを絡めた通信は、同期的に進めるとユーザーの体験を損なうことが多く非同期で管理することが中止になると思います。
通信・作業中であることを知らせる
そういった場合ですが、ユーザーには作業中であることを知らせておきたいという場面もたくさんあります。
iOSではNSProgress
という進捗管理オブジェクトやUIProgressView
という進捗を表示するUIが用意されていて、そのあたりも簡単に知らせておくことができます。
でも、もっと簡単に通信中であるということを通知する方法としてステータスバーにインジケータを表示するという方法もあります。
これは、UIApplication
のnetworkActivityIndicatorVisible
をYES
にしている場合は常に表示されるという簡単な仕組みで動作します。
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES
メインスレッドで、動作を制御するのであれば通信開始時にYES
として通信終了時にNO
とするだけで良いのですが、マルチスレッドでバックグラウンドで通信を動かす場合は、1つの通信が終わっても他が終わっていない可能性があるので、単純にNO
とプロパティを変更するだけでは不十分です。
なので、通信を管理するマネージャオブジェクトを作ったりして、通信中のオブジェクトの数を保持しておくことやNSOperationQueueで非同期のスレッドを管理しているのなら、実行中のOperationの数をループで数えることなどが考えられます。
ほかにも、インジケータ用のクラスを用意しておいてそのクラスに通信の開始と通信の終わりを知らせるという方法もあります。
ぼくはこの案を採用していてシングルトンのクラスで通信の開始でカウントを増やしと通信が終了したらカウントを減らすという簡単なクラスです。
クラスの中身はこんな感じです。
@interface JAGNetworkMonitor ()
@property ( nonatomic ) int count;
@end
@implementation JAGNetworkMonitor
+ (instancetype)sharedManager{
static JAGNetworkMonitor *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (void)increaseNetworkConnectionCount{
_count ++;
[self updateIndicatorWithCount:_count];
}
- (void)decreaseNetworkConnectionCount{
_count --;
[self updateIndicatorWithCount:_count];
}
- (void)updateIndicatorWithCount:(int)count{
[UIApplication sharedApplication].networkActivityIndicatorVisible = count;
}
@end
使い方は、以下のように使います。
JAGNetworkMonitor *monitor = [JAGNetworkMonitor sharedManager];
[monitor increaseNetworkConnectionCount];
[[[NSOperationQueue alloc] init] addOperationWithBlock:^{
// 何かしらの通信作業
// 通信終了後に呼ぶ
[monitor decreaseNetworkConnectionCount];
}];
こうすることで、一元的に通信している状態を管理できますので便利に使っています。
さいごに
ぼくは、AFNetworking以外にも通信に使うクラス、ライブラリが混在する場合があったので、こういったアプローチをしていますが、AFNetworkingにはAFActivityIndicatorManagerという専用のクラスがあって、それを使えばわざわざ数を管理する必要はありません。