次のコードがあります。
- (void)test_with_running_runLoop {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSTimeInterval checkEveryInterval = 0.05;
NSLog(@"Is main queue? : %d", dispatch_get_current_queue() == dispatch_get_main_queue());
dispatch_async(dispatch_get_main_queue(), ^{
sleep(1);
NSLog(@"I will reach here, because currentRunLoop is run");
dispatch_semaphore_signal(semaphore);
});
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW))
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:checkEveryInterval]];
NSLog(@"I will see this, after dispatch_semaphore_signal is called");
}
- (void)test_without_running_runLoop {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSLog(@"Is main queue? : %d", dispatch_get_current_queue() == dispatch_get_main_queue());
dispatch_async(dispatch_get_main_queue(), ^{
sleep(1);
NSLog(@"I will not reach here, because currentRunLoop is not run");
dispatch_semaphore_signal(semaphore);
});
NSLog(@"I will just hang here...");
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW));
NSLog(@"I will see this, after dispatch_semaphore_signal is called");
}
以下を生成します。
Starting CurrentTests/test_with_running_runLoop
2012-11-29 08:14:29.781 Tests[31139:1a603] Is main queue? : 1
2012-11-29 08:14:30.784 Tests[31139:1a603] I will reach here, because currentRunLoop is run
2012-11-29 08:14:30.791 Tests[31139:1a603] I will see this, after dispatch_semaphore_signal is called
OK (1.011s)
Starting CurrentTests/test_without_running_runLoop
2012-11-29 08:14:30.792 Tests[31139:1a603] Is main queue? : 1
2012-11-29 08:14:30.797 Tests[31139:1a603] I will just hang here...
私の質問は互いに関連しています:
私の理解が正しければ、メイン キュー (dispatch_get_main_queue()) はシリアル キューです。メイン キュー/メイン スレッドを dispatch_semaphore_wait でブロックしているのに、最初のテスト ケースで「currentRunLoop が実行されているため、ここに到達します」と表示されるのはなぜですか(2 番目のケースは問題ありません。私の理解では、そうです。何をすべきか)?
現在実行中のタスクがブロックされているシリアルキューで、現在のタスクがロック解除される前に、次のタスク (ああ、この不思議な runLoop:beforeDate:) をディスパッチするにはどうすればよいでしょうか?
非常に多くのことが(SOについても)この問題に依存しているため、これについて詳細かつ包括的な回答を聞きたいです。
更新:受け入れられた回答に加えて、この SO トピックには、この質問に対する適切な回答があります:完了時にメイン キューを呼び出す単体テスト async キューのパターン