0

内部にいくつかの単純なコードを含む IBAction があります。

-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [self dolengthyaction];
}

'textfield' は nib ファイルの NSTextField で、-'dolengthyaction' は実行が完了するまでに約 1 分かかる関数です。

私の質問は、「dolengthyaction」の実行が完了するまでテキストフィールドが表示されないのはなぜですか? 長いアクションが始まる前に明らかにしてほしい。これは固有の問題ですか、それとも私のコードに何か問題がありますか? (または私のコードの別の部分で?)

私はまだプログラミングが得意ではないので、言葉遣いや書式設定が間違っていたら申し訳ありません。

編集: この IBAction と -dolengthyaction 以外にはあまりありません...

-(void)doLengthyAction {
    sleep(10);
}
-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [self doLengthyAction];
    [textfield setHidden:YES];
}

私が実際にやりたいことは、アクションの実行中にラベルを表示し、完了したら非表示にすることだけです。

基本的にこれが意味することは、現在まったく表示されていないということです。

実際には、-doLengthyAction では sleep(10) ではなく、約 50 Mb の素材をコピーする NSFileManager 操作です。コードはかなり長いですが、投稿したい場合は投稿できます。sleep() でテストしましたが、どちらも機能しません。

4

6 に答える 6

6

すべての描画操作 (ビューの非表示と表示を含む) は、実行ループからトリガーされます。実行ループは、関数が戻るまで次のイベントを実行できません。

実行に 1 秒以上かかる操作がある場合は、スレッドで実行する必要があります。完了したら、performSelectorOnMainThread を使用して、メイン スレッドで UI を変更します。

于 2010-05-04T02:00:42.790 に答える
5

前の回答のいくつかで述べたように、アプリケーションは再描画する前にメインの実行ループに戻る必要があります(これは、多くの変更を加えたときに再描画を回避するための最適化です)。

長時間実行する場合は、バックグラウンドスレッドで処理する必要があります。そうしないと、操作の実行中にUIがビーチボールになります。

10.6以降をターゲットにしている場合は、次のようにGCDとブロックを使用して、バックグラウンドで簡単に実行できます(実行するために複数のメソッドを定義する必要はありません)。

-(void)doLengthyAction {
    sleep(10);
}
-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self doLengthyAction];
        dispatch_async(dispatch_get_main_queue(), ^{
            [textfield setHidden:YES];
        });
    });
}

もちろん、これを使用することで、長いアクションで行われていることがスレッドセーフであることを確認する必要がありますが、最終的にはユーザーエクスペリエンスが向上します。このタイプのCGDコードの詳細については、こちらをお読みください

于 2010-05-04T02:24:23.637 に答える
1
-(void)doLengthyAction {
     sleep(10);
    [textfield setHidden:YES];
} 

-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(doLengthyAction) userInfo:nil repeats:NO];
}
于 2010-05-04T01:46:06.823 に答える
1

コードの残りの部分に何か問題があると思います。これは起こらないはずです。

もっと投稿しますか?

于 2010-05-04T01:00:36.353 に答える
1

残りのコードを見ないと正確に何が起こっているのかはわかりませんが、ハックな方法は次のことを試すことです。

-(IBAction)change:(id)sender {
   [textfield setHidden:NO];
   [self performSelector:@selector(doLenghtyAction) withObject:nil afterDelay:0.1]; --> or maybe even 0.0
 }
于 2010-05-04T01:13:22.817 に答える
0

これを試して:

-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [[textfield window] display]; // force the window to update
    [self doLengthyAction];
    [textfield setHidden:YES];
}
于 2010-05-04T03:38:26.580 に答える