web-dev-qa-db-ja.com

次の実行ループで実行:GCDの何が問題になっていますか?

私はこれらの2つのアプローチを試しています:

dispatch_async(dispatch_get_main_queue(),^{
    [self handleClickAsync];
});

そして

[self performSelector:@selector(handleClickAsync) withObject:nil afterDelay:0];

ボタンの押下に応答して。

2つ目は、UIButtonを期待どおりに強調表示し、次の実行ループでhandleClickAsyncを実行できるようにします(確かに「しばらくしてから」と思います)。 1つ目は、操作が完全に完了するまでUIButtonインスタンスを点灯させません。

GCDでこれを行う正しい方法は何ですか、それともperformSelectorがまだ唯一の方法ですか?

28
Dan Rosenstark

答えはここにあると思います メインディスパッチキューの説明

このキューは、アプリケーションの実行ループ(存在する場合)と連携して、キューに入れられたタスクの実行を、実行ループに接続されている他のイベントソースの実行とインターリーブします。

つまり、メインディスパッチキューはセカンダリキューを設定します(メインキューに送信されたブロックを処理するためにUIApplicationMain()によって提供される標準イベントキューと一緒に。ブロックがキューに存在する場合、実行ループは交互になりますメインイベントキューとディスパッチキューからタスクをデキューします。一方、-performSelector:withObject:afterDelay:delayパラメータの 参照 は次のことに注意してください。

0の遅延を指定しても、必ずしもセレクターがすぐに実行されるとは限りません。セレクターは引き続きスレッドの実行ループのキューに入れられ、できるだけ早く実行されます。

したがって、実行セレクターを使用すると、操作はメインイベントキューの最後にキューに入れられ、キュー内のその前にあるすべてのものが完了するまで実行されません(おそらく、UIButtonをハイライト解除するコードが含まれます) 処理されました。ただし、メインディスパッチキューを使用すると、ブロックがセカンダリキューに追加され、メインキューに他のブロックがないと想定して、すぐに(つまり、次の実行ループで)処理される可能性があります。この場合、実行ループがセカンダリブロックキューからのイベントを処理している間、ボタンのハイライトを解除するコードはメインイベントキューに残っています。

40
Sean

私はこれがあなたのポイントに当たると思います:

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
     //bla bla bla
}];
26
Feng