フリーズのヒントに関する質問の2番目の部分については、次のようにします。
dispatch_sync
キューを呼び出すときは、このキューが現在のキュー( )ではないことを常に確認してdispatch_get_current_queue()
ください。なぜならdispatch_sync
、最初のパラメータとして渡されたキューにブロックをキューに入れ、次にこのブロックが実行されるのを待ってから続行するからです。
したがってdispatch_get_current_queue()
、ブロックをエンキューするキューとが同じである場合、つまりメインキューの場合、メインキューはdispatch_syncの呼び出しでブロックされ、メインキューがブロックを実行するまでブロックされますが、できません。キューがブロックされ、ここに美しいデッドロックが発生します。
1つの解決策(iOS6までの[編集]):
dispatch_queue_t main = dispatch_get_main_queue();
dispatch_block_t block = ^
{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationAuthenticationSuccess object:nil userInfo:ret];
};
if (dispatch_get_current_queue() == main)
block(); // execute the block directly, as main is already the current active queue
else
dispatch_sync(main, block); // ask the main queue, which is not the current queue, to execute the block, and wait for it to be executed before continuing
[編集]注意してくださいdispatch_get_current_queue()
。デバッグ目的でのみ使用され、本番環境では使用されません。実際、dispatch_get_current_queue
iOS6.1.3以降は非推奨になっています。
メインキュー(メインスレッドのみに関連付けられている)の特定のケースにいる場合は、代わりに[NSThread isMainThread]
@meaning-mattersで提案されているようにテストできます。
ちなみに、あなたdispatch_sync
はあなたの場合にそうする必要がありますか?通知を少し後で送信し、送信されるまでブロックしないようにすることは、あなたのケースでは許容できると思います。したがって、dispatch_async
(キュー比較条件を使用して必要とする代わりに)を使用することも検討dispatch_sync
できます。これにより、デッドロックの問題も回避できます。