2012-05-03 4 views
21

私はこれらの二つのアプローチしようとしている:ボタンを押しに対応して次の実行ループで実行:GCDで何が問題になっていますか?

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

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

を。

UIButtonは、次の実行ループでhandleClickAsyncを実行して実行することができます(確かに「後で」と思われます)。最初の操作では、操作が完全に完了するまで、UIButtonインスタンスが点灯しません。

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

+0

は、おそらくあなたは別のディスパッチキューの内側からこれを呼び出していますか?存在する場合は、すべてのコマンドをキュー内で順番に実行します。操作を開始する前にこのメソッドを呼び出すことは可能ですか? –

+0

わかりません。私はこれを 'touchesEnded'から直接呼び出しています。これは' UIView'サブクラス(またはこの場合はUIButton)で無料で提供されます。 –

+0

なぜ私はdispatch_asyncとrunloopの実行との関連付けをしているのか分かりません。 –

答えて

36

私は答えがここに発見されたと信じてdiscussion of the main dispatch queue

このキューは、アプリケーションの実行ループで動作します(存在する場合)付属の他のイベントソースの実行とキューに入れられたタスクの実行をインターリーブします実行ループに転送します。言い換えれば

、メインディスパッチキューは、メインキューに提出したブロックを処理するためのUIApplicationMain()が提供する標準のイベントキューと一緒に(二次キューを設定します。 ブロックがキューに存在している場合は、実行ループはなります0の遅延を指定

は必ずしもセレクタがすぐに実行されることはありません。一方、-performSelector:withObject:afterDelay:ノートのdelayパラメータのreferenceというメインイベントキューとディスパッチキューからデキュー代替タスク。セレクタは依然としてスレッドの 'ループを実行し、できるだけ早く実行します。あなたは、セレクタを実行する際に使用

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

+0

これは理にかなっています。ショーンは、実証的な現実を説明しているようです。私は数日待って、他の種類の回答が何か入ってくるのを見るのを待つつもりです。 –

+0

うーん、おそらく誰かが@bbumのような人に入ってこのことを確認してくれるだろうが、だから、これを暫定的に最善の答え(永遠に)としてマークします。再度、感謝します。 –

22

私は、これはあなたのポイントをヒットすると思う:

[[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
    //bla bla bla 
}]; 
+0

それは私のためにしました。 :) –

+0

はい。これは動作しています! – Klaas

関連する問題