時間のかかる処理を行っている間アプリに何の反応もないと、ユーザーにはアプリがちゃんと動いているのかどうか分かりません。
インジケータは「処理してますよ〜」というサインをユーザーに送ることができるのでけっこう重要です。
UIActivityIndicatorViewを使えば簡単にインジケータを扱えるんだろうなあとタカをくくっていたらちょっとハマったのでメモしておきます。
巷の解説書などによると基本的には下のような流れでUIActivityIndicatorViewを利用します。
まず、オブジェクトを初期化
フレームをセットUIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
indicator.frame = CGRectMake((100.0, 100.0, 50.0, 50.0);親Viewに追加[self.view addSubview:indicator];startAnimatingメソッドを呼び出せばインジケーターが表示される。[indicator startAnimating];stopAnimatingメソッドを呼び出せばインジケーターが隠れる。[indicator stopAnimating];ところが startAnimating と stopAnimating を同じスレッド内で実行してもインジケータがうまく切り替わりません。
ようするに
- (void)doSomething {
...
[indicator startAnimating];
// なにか重い処理を実行...
[indicator stopAnimating];
}こんな感じであるメソッド内でstartAnimatingとstopAnimatingを実行してもきちんとインジケータが隠れてくれません!(出っぱなしになる)
どうやらstopAnimatingはstartAnimatingとは別スレッドで呼び出さなければならないらしいのです。
幸いNSObjectクラスにはperformSelectorInBackground:withObject:というメソッドが用意されているので、それを利用すれば簡単に別スレッドで何らかの処理をすることができます。
そんなわけでサンプルコードはこちら。
- (void)loadView {
...
// 初期化したオブジェクトをインスタンス変数に追加しておく
self.indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
indicator.frame = CGRectMake((100.0, 100.0, 50.0, 50.0);
[self.view addSubview:indicator];
}
- (void)doSomething {
[self.indicator startAnimating];
[self performSelectorInBackground:@selector(doInBackground) withObject:nil];
}
- (void)doInBackground {
// 別スレッドで実行するメソッドではNSAutoreleasePoolを使わなければならない
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
// なにか重い処理を実行
...
[self.indicator stopAnimating];
[pool drain];
}基本的にはこれでインジケータの表示/非表示の切り替えができるようになります。


2 comments:
わかりやすい記事で参考になりました!
違いますよ、これ。
>どうやらstopAnimatingはstartAnimatingとは別スレッドで呼び出さなければならないらしいのです。
どちらもメインスレッドから呼出すべきなのです。
iOSは(その他一般イベントドリブンフレームワークも)メインスレッド(イベントループ)で重い処理をしてはいけません。
メインスレッドで重い処理すれば表示も入力も全て止まってしまいます。(いわゆるフリーズ)
元々の問題がメインスレッドで重い処理をしていた事なので、重い処理を別スレッドで表示するところまでは妥当ですが、stopAnimatingはメインスレッドで実行するべきです。
「動いたから良いじゃん」と言われてしまえば返す言葉は無いですが…
大きなお世話なのは重々承知しておりますが、この記事を真に受ける人がいる様なので念のため。
コメントを投稿