ランループのないバックグラウンドスレッドでは performSelector:withObject:afterDelay: が使用できない。
理由は、
- performSelector:withObject:afterDelay: は、現在のスレッド上で遅延実行される。
- 遅延時間経過後にはスレッドが消滅している。
このため、
- ランループの終了を遅延させる。
- dispatch_after() を使用する。
のどちらかで対処。違いは前者が同じスレッド上で実行されるのに対し、後者は別のバックグラウンドスレッド上で動作する、だけ?
- (IBAction)button1Action:(id)sender
{
// バックグラウンドスレッドで実行
[self performSelectorInBackground:@selector(selectorInBackground) withObject:nil];
}
- (void)selectorInBackground
{
@autoreleasepool {
NSLog(@"(A) %@", [NSThread currentThread]);
// (1) ↓runUntilDate: でメソッドの実行時間までランループの終了を遅延させる
[self performSelector:@selector(selectorFromBackground1) withObject:nil afterDelay:5.f];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5.f]]; // ←これがないとダメ。
// (2) ↓dispatch_after()だと待たなくても別のスレッド上で遅延実行される。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
[self selectorFromBackground2];
});
}
}
- (void)selectorFromBackground1
{
NSLog(@"(B) %@", [NSThread currentThread]);
}
- (void)selectorFromBackground2
{
NSLog(@"(C) %@", [NSThread currentThread]);
}
>出力
2012-06-30 01:58:28.201 Sandbox 40035:10e03 (A) <NSThread: 0x595d3f0>...
2012-06-30 01:58:33.206 Sandbox 40035:10e03 (B) <NSThread: 0x595d3f0>...
2012-06-30 01:58:38.212 Sandbox 40035:10e07 (C) <NSThread: 0x4d540e0>...
(A) と (B) は同じ。(C) は別スレッドで実行されているのがわかる。