UI 操作と競合しないスレッドによるタイマー表示 ― 2012年07月21日 11:22
画面にUIPickerと、NSTimerを使ったタイマーを配置した場合、カウント中にピッカーを回転させるとその間カウンターの表示が停止する。これは、NSTimer、UIViewの表示がともにメインスレッドで動作するからです。
これを回避するには、タイマーのカウント部分を別のスレッドにすることですが、カウンターの更新部分はUI にアクセスすることになる( ...メインスレッドに用意したメソッドを呼び出す)あまりすっきりしない。iOS 4 から導入されたGCDならメインのUI にアクセスできるから扱いやすい。これを直接利用してもよいが、NSOperationQue もGCDが使われるようになっているからこれを使ってテストしてみたが、動作は快適である。
// タイマーの更新(テストコード)
- (void) countUpdate
{
NSOperationQueue *queue = [[[NSOperationQueue alloc]init] autorelease];
[queue addOperationWithBlock:^{
while (1) {
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[mainQueue addOperationWithBlock:^{
// カウントアップ
count_++;
// 再生時間を更新
countLabel_.text = [NSString stringWithFormat:@"%d", count_];
}];
[NSThread sleepForTimeInterval:1.0f];
}
}];
}
参考:
詳解 iOS 5 プログラミング
これを回避するには、タイマーのカウント部分を別のスレッドにすることですが、カウンターの更新部分はUI にアクセスすることになる( ...メインスレッドに用意したメソッドを呼び出す)あまりすっきりしない。iOS 4 から導入されたGCDならメインのUI にアクセスできるから扱いやすい。これを直接利用してもよいが、NSOperationQue もGCDが使われるようになっているからこれを使ってテストしてみたが、動作は快適である。
// タイマーの更新(テストコード)
- (void) countUpdate
{
NSOperationQueue *queue = [[[NSOperationQueue alloc]init] autorelease];
[queue addOperationWithBlock:^{
while (1) {
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[mainQueue addOperationWithBlock:^{
// カウントアップ
count_++;
// 再生時間を更新
countLabel_.text = [NSString stringWithFormat:@"%d", count_];
}];
[NSThread sleepForTimeInterval:1.0f];
}
}];
}
参考:
詳解 iOS 5 プログラミング
最近のコメント