9

現在のメソッドが渡され、UI が更新された後にメソッドを実行したいと考えています。そのために、[object performSelector:@selector(someSelector) withObject:someObject afterDelay:0.0]今使っています。Apple のドキュメントによると、これにより NSTimer が作成され、セレクターがトリガーされて現在の NSRunLoop に追加されます。しかし、私はこれを非常にエレガントだとは思いません。ココアにタイマーなどを作成させずに、セレクターを現在の実行ループに直接エンキューする簡単な方法はありますか?

performSelectorOnMainThread:withObject:waitUntilDone:(メインスレッドにいる場合)またはオーバーヘッドを減らしperformSelector:onThread:withObject:waitUntilDone:waitUntilDone:NOやりたいことはありますか?

乾杯と前もって感謝します

ミスターメイジ

4

5 に答える 5

6

Cocoa はイベント駆動型です。「現在の実行ループ内でセレクターをキューに入れる」ことはありません。簡単に言えば、アプリケーションに送信されたイベント (ユーザー入力、タイマー、ネットワーク アクティビティなど) によって実行ループが実行され、ループの実行中に何かが発生します。もちろん「ディテール」もありますが、これが最も基本的な振る舞いです。

セレクターの実行を現在の実行ループの最後に延期したい場合は、それを最後に呼び出すか、(非常に近い) 次のループの実行で実行するように依頼します。-performSelector:... メソッド、これを行う正しい方法です。それらは、物事が起こる原因となるイベントをもたらすタイマーを作成します。

詳細については、Cocoa イベント処理ガイドを参照してください。

于 2009-11-14T16:21:14.300 に答える
4

あなたが強調している -performSelector:withObject:afterDelay: メソッドについて、洗練されていないものは何もありません。このメソッドは、実行ループの現在のサイクルの完了後に実行されるタスクをキューに入れるだけです。リンク先のセクションのドキュメントから

次の実行ループ サイクル中およびオプションの遅延期間の後に、指定されたセレクターを現在のスレッドで実行します。セレクターを実行するために次の実行ループ サイクルまで待機するため、これらのメソッドは、現在実行中のコードから自動的に最小限の遅延を提供します。キューに入れられた複数のセレクターは、キューに入れられた順序で次々に実行されます。

これを管理するために NSTimer オブジェクトは作成されません。セレクターは、一定の遅延後に実行されるようにキューに入れられるだけです (わずかな遅延とは、実行ループ サイクルの完了直後を意味します)。UI の更新後に発生させたいアクションについては、これが最も簡単な方法です。

より明示的なスレッド化されたキューイングについては、NSOperationsおよびNSOperationQueuesを参照してください。maxConcurrentOperationCount が 1 の NSOperationQueue は、操作を順に実行できます。

于 2009-11-14T20:23:45.447 に答える
4

私は NSRunLoop メソッド "performSelector:target:argument:order:modes:" を好みます。実行ループの次の繰り返しまでセレクターを実行しないことが保証されており、任意の遅延などを指定する必要はありません。

于 2009-11-15T20:19:20.110 に答える
2

私はこの手法を自分で何度も使用しており、それほどエレガントではないと思います...ただし、試すことができる代替手段は次のとおりです。

performSelectorOnMainThread:withObject:waitUntilDone:NO.

すでにメインスレッドにいるからといって、それが機能しないという意味ではありません(実際、ドキュメントはメインスレッドから呼び出されたときに発生する動作を参照しています)...そして、waitUntilDoneが設定されている場合も同じ動作になると思いますNO に設定すると、セレクターを実行する要求がキューに入れられ、現在の実行ループが終了したときにセレクターが実行されます。

于 2009-11-14T21:16:02.830 に答える