メイン キューにブロックを同期的にディスパッチする必要があります。現在メイン スレッドで実行されているかどうかはわかりません。単純な解決策は次のようになります。
dispatch_sync(dispatch_get_main_queue(), block);
しかし、メイン キューで実行中のブロック内にいる場合、この呼び出しによってデッドロックが発生します。(同期ディスパッチはブロックが終了するまで待機しますが、現在のブロックが終了するまで待機しているため、ブロックの実行は開始されません。)
次のステップは、現在のキューを確認することです。
if (dispatch_get_current_queue() == dispatch_get_main_queue()) {
block();
} else {
dispatch_sync(dispatch_get_main_queue(), block);
}
これは機能しますが、見苦しいです。少なくともカスタム関数の背後に隠す前に、この問題に対するより良い解決策はありませんか? ブロックを非同期にディスパッチする余裕がないと強調します。アプリは、非同期にディスパッチされたブロックが「遅すぎる」実行になってしまう状況にあります。
ベストアンサー1
私はMacとiOSのアプリケーションでこのようなものを頻繁に使用する必要があるので、次のヘルパー関数を使用します(元々はこの答え):
void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
if ([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
}
通話方法は
runOnMainQueueWithoutDeadlocking(^{
//Do stuff
});
これは、上で説明したプロセスとほぼ同じであり、独自にこれと似たものを作成した他の開発者数名と話をしたことがあります。
[NSThread isMainThread]
をチェックする代わりに使用しましたdispatch_get_current_queue()
。その機能に関する注意事項かつてこれを身元検査に使用しないよう警告され、この呼び出しはiOS 6では廃止されました。