5

新しいスレッドを生成し、その中で新しいコントローラーを UINavigationController にプッシュすると、次のようなコードを使用します...

(a) 機能しない

-(void)myCallbackInThread
{
    // move on...
    UIApplication* app = [UIApplication sharedApplication];
    [app changeView];
}

次に、ビューが表示されますが、ユーザー入力に応答しません。

このようにコードを変更すると

(b) 働く

-(void)myCallbackInThread
{
    // move on...
    UIApplication* app = [UIApplication sharedApplication];
    [app performSelectorOnMainThread:@selector(moveToMain) withObject:nil waitUntilDone:FALSE];
}

その後、すべてがうまく機能します。

理由についてのヒントはありますか?

4

4 に答える 4

2

あなたの場合、それは [app changeView] で何が起こっているかに大きく依存しますが、応答を停止する理由は、新しいセカンダリ スレッドにイベントをディスパッチする実行ループがない可能性が最も高いです (これについては以下で詳しく説明します)。ただし、一般に、セカンダリ スレッドから GUI を更新することは非常に悪い考えです。既にお気づきのように、これらのイベントはすべてメイン スレッドを通過する必要があります。

最初の例ではなく 2 番目の例が機能する主な理由は、UIApplication がメイン スレッドで実行ループとイベント ディスパッチャーをセットアップして処理するためです。そのため、performSelectorInMainThread を呼び出すと、セレクターがメインの実行ループにディスパッチされ、GUI 入力やその他のイベントを処理できるようになります。イベント ディスパッチャーも、メイン スレッドの UIApplication によって実行および管理されます。

したがって、基本的に、セカンダリ スレッドで GUI 管理アクティビティを実行しないでください。それらをメインスレッドにディスパッチします。また、セカンダリ スレッドで処理が必要な場合 (タイマーや非同期呼び出しなど)、そのスレッドで独自の実行ループを開始して管理する必要があります (実行ループの管理の詳細については、 NSRunLoopを参照してください)。

于 2008-11-08T00:35:34.020 に答える
2

iPhoneのスレッド化ドキュメントでこれを見つけました

アプリケーションにグラフィカル ユーザー インターフェイスがある場合は、ユーザー関連のイベントを受け取り、アプリケーションのメイン スレッドからインターフェイスの更新を開始することをお勧めします。このアプローチは、ユーザー イベントの処理とウィンドウ コンテンツの描画に関連する同期の問題を回避するのに役立ちます。Cocoa などの一部のフレームワークでは、通常、この動作が必要ですが、ユーザー インターフェイスを管理するためのロジックが簡素化されるという利点もあります。

実際に何かが表示されてもユーザー入力を受け取ることができない原因はまだわかりませんが、今後はそのガイドラインに従います。

于 2008-10-03T15:42:56.757 に答える
2

ドキュメントにあるように、「特定のグラフィカル操作についてよくわからない場合は、メイン スレッドから実行することを計画してください。」

従うべき良い経験則は、クラスがスレッドセーフであると明示的に文書化されていない場合、おそらくそうではないということです。さらに、スレッド セーフであると文書化されていないコードは、複数のスレッドで使用された場合に高速に失敗しない可能性がありますが、ご覧のとおり、未定義の動作を示すだけです。

于 2008-10-03T16:12:43.403 に答える
0

UIKit または AppKit の UI コードはほとんどスレッドセーフではありません。どのように失敗するかは関係ありません。なぜなら、どのように失敗するかを心配している場合は、さまざまな OS リリース間で微妙に変化するあらゆる種類の奇妙なバグを引き起こす何かをしているからです。

私の最善のアドバイスは、ドキュメントが安全であると述べていない限り、バックグラウンド スレッドのものを使用しないことです。

于 2008-11-08T01:11:00.313 に答える