ジェイコブが指摘するように、それらは同じように見えるかもしれませんが、それらは異なるものです。実際、すでにメインスレッドで実行している場合、メインスレッドへのアクションの送信を処理する方法には大きな違いがあります。
私は最近これに遭遇しました。そこでは、メインスレッド上の何かから実行されることもあれば、実行されないこともある一般的なメソッドがありました。特定のUIアップデートを保護するために、私は-performSelectorOnMainThread:
問題なくそれらを使用していました。
メインキューでの使用に切り替えるとdispatch_sync
、このメソッドがメインキューで実行されるたびに、アプリケーションがデッドロックしていました。のドキュメントを読むと、次のようになりdispatch_sync
ます。
この関数を呼び出して現在のキューをターゲットにすると、デッドロックが発生します。
どこで-performSelectorOnMainThread:
見るか
待つ
指定されたセレクターがメインスレッドのレシーバーで実行されるまで、現在のスレッドがブロックするかどうかを指定するブール値。このスレッドをブロックするには、YESを指定します。それ以外の場合は、NOを指定して、このメソッドをすぐに返します。
現在のスレッドがメインスレッドでもあり、このパラメーターにYESを指定すると、メッセージはすぐに配信および処理されます。
私はまだGCDの優雅さ、それが提供するより良いコンパイル時チェック、そして引数などに関するより大きな柔軟性を好みます。そこで私はデッドロックを防ぐためにこの小さなヘルパー関数を作りました:
void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
if ([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
}
更新: Dave Dribinがの警告セクションをdispatch_get_current_queue()
指摘したことに応じて[NSThread isMainThread]
、上記のコードで使用するように変更しました。
次に使用します
runOnMainQueueWithoutDeadlocking(^{
//Do stuff
});
元のメソッドがどのスレッドで実行されたかを気にせずに、メインスレッドで保護する必要のあるアクションを実行します。