アクションで長時間のタスクを実行しています。現在の場所を表示したいと思います。そのために、テキスト フィールドを作成し、setStringValue で試しました。
[textField setStingValue: [NSSting stringWithFormat:@"%ld",currentValue]]
コードは機能しますが、残念ながら、反復ごとに NSTextField を更新するのではなく、アクション全体が完了したときに更新されます。
私は何を間違っていますか?
アクションで長時間のタスクを実行しています。現在の場所を表示したいと思います。そのために、テキスト フィールドを作成し、setStringValue で試しました。
[textField setStingValue: [NSSting stringWithFormat:@"%ld",currentValue]]
コードは機能しますが、残念ながら、反復ごとに NSTextField を更新するのではなく、アクション全体が完了したときに更新されます。
私は何を間違っていますか?
これは、Cocoa フレームワークを使用するアプリケーションがイベント ループを使用して操作を実行し、イベントが完全に逐次的に発生するためです。
イベントとは、基本的に、フレームワークの設計者が予測できなかったり、遅延して実行するのが便利だと判断できなかったあらゆる種類のアクションです。クリックがいつ実行されるかは予測できないため、イベントと見なす必要があります。また、効率上の理由から (必要がなければコンポーネントを何度も再描画したくないため)、再描画アクションもイベントです。
アクションはユーザー イベント (たとえば、ボタンのクリックはイベント) に応答して実行されるため、完了するまでキューで待機している他のすべてのイベントをブロックします。ただし、コンポーネントは、別のフレームワークによってトリガーされるイベントに応答して再描画されるため、テキスト フィールドは、アクション自体の再描画が完了するまで待機する必要があります。これが、アクション内からテキスト フィールドの値を視覚的に変更できない理由です。
タスクの進行状況をユーザーに通知するには、別のスレッドで実行する必要があります。スレッドについては言いたいことがたくさんあるので、スレッドについていくつか読んだほうがいいでしょう。また、バックグラウンド スレッドで長いアクションを実行し、それに応じてインターネット全体で Cocoa の UI を更新する方法の例がたくさんあることも確信しています。
UIコンポーネントをクリックして、それがActionブロックに入ると、コードはメインスレッド(UIをペイントしているのと同じスレッド)で実行されます。そのブロックで長時間実行されている操作を実行すると、実行していることを実行するのに忙しいため、実行が完了するまでペイントされません。ペイントスレッドがハイジャックされています。
他の場所で述べたように、別のスレッドを生成してから、新しいスレッドに長時間実行操作を実行させ、場合によってはメッセージを送信してUIをメインスレッドで更新する必要があります。
次のステップとして、NSThreadに関するAppleのドキュメントを読んでください。具体的には次のとおりです。
+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
スレッド化は重要なドメイン領域であることに注意してください。注意しないと、奇妙な動作に備えることができます。