0

接続していますUILabel

@property (strong, nonatomic) IBOutlet UILabel *label;

そして、ボタンによってトリガーされるアクション

- (IBAction)buttonPressed:(UIButton *)sender;

ボタンが押されたときに、ラベルを更新して、実行中の秒を最大 3 分まで表示したいので、

- (IBAction)buttonPressed:(UIButton *)sender {
    for (int i =0; i < 180; ++i) {
        [label setText:[NSString stringWithFormat:@"%d", i]];
        sleep(1);
    }
}

確認、メソッドが呼び出され、タイマーがカチカチ音をたてています..ラベルテキストは変更されません。私は何を間違っていますか?

4

4 に答える 4

2

sleep()、UIスレッドがそれ自体を更新することを許可しません。

これは、元のコードに厳密に一致するGCDを使用したサンプルです。注:これを行うには、より良い方法があります(:を参照dispatch_after())。

- (IBAction)buttonPressed:(UIButton *)sender {
    [label setText:[NSString stringWithFormat:@"%d", 0]];

    dispatch_queue_t queue = dispatch_queue_create("com.test.timmer.queue", 0);
    dispatch_async(queue, ^{
    for (int i = 1; i < 180; ++i) {
        sleep(1);
        dispatch_async(dispatch_get_main_queue(), ^{
            [label setText:[NSString stringWithFormat:@"%d", i]];
        });
    });
}
于 2012-07-26T03:10:14.183 に答える
2

あなたの sleep() はメインスレッドにあり、ビューは更新できません。NSTimer を使用してそれを行うことができます。

- (void)update
{
    [label setText:[NSString stringWithFormat:@"%d", i]];
    i++;
    if(i>=100)
    {
        [timer invalidate];
    }
}

- (IBAction)buttonPressed:(UIButton *)sender
{

    timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(update) userInfo:nil repeats:YES];
    [timer fire];
}
于 2012-07-26T03:27:53.790 に答える
1

コントロールを更新するには、runloopに戻る必要があります。タイトなループの代わりに、1秒ごとに起動するNSTimerを使用する必要があります。

あまりお勧めしませんが、setTextの直後に呼び出すと、次のように機能する場合もあります。

[[NSRunLoop currentRunLoop] acceptInputForMode:NSDefaultRunLoopMode beforeDate:nil];
于 2012-07-26T03:09:19.530 に答える
0

すべての UI 関連はメイン スレッドで行われます。ランタイムをメイン スレッドで強制的にスリープさせると、文字通り UI がフリーズします。それを 180 回実行すると、不満を抱くエンドユーザーが 1 人できます。

于 2012-07-26T04:09:16.660 に答える