0

UIProgressView をカウント ダウン タイマーとして実装しました。その値は 1.5 秒で 1.0 から 0.0 に減少します。

すでに動いていましたが、問題は1.5秒以上かかり、プログレスビューの値が0.0になるまでに2.0~2.5秒ほどかかりました

わずか 1.5 で実行するために、呼び出されるたびに進行状況の値を 0.001 ずつ減らしました。減少メソッドは、0.0015 秒間隔で呼び出されます。

以下は私がそれを行う方法です。わずか1.5秒よりも長く実行される問題があるかどうかはわかりませんか?

- (void)decreaseProgress {
    if (currentProgress > 0.0000f) {
        currentProgress -= 0.001f;
        [_timeLineProgress setProgress:currentProgress animated:YES];

        [self performSelector:@selector(decreaseProgress) withObject:self afterDelay:0.0015 inModes:@[NSDefaultRunLoopMode]];
    } else {
        [self stopTimer];
    }
}
4

2 に答える 2

3

進行状況をアニメーション化するには、reduceProgress メソッドでこのコードを試してください

[UIView animateWithDuration:1.5 animations:^{
        [_timeLineProgress setProgress:0.0 animated:YES];
    }];
于 2015-07-01T05:18:36.700 に答える
1

進行状況ビューを 1.5 秒で 1000 回更新しようとしています。画面は 1 秒間に 60 回しか更新されないため、これは速すぎます。つまり、進行状況バーが実際に画面に再描画されるたびに、進行状況バーを 10 回以上更新しています。

代わりに、0.1 秒間隔で 15 回の更新を提案し、進行状況バーを毎回 1/15 ずつ変更します。

コードのパフォーマンスを確認する 1 つの方法は、CACurrentMediaTime関数を使用してタイムスタンプを取得することです。その方法を示すサンプル コードを次に示します。progressStart変数は、ボタン プレス イベントが発生したときのタイムスタンプであり、NSLog開始時刻からの経過時間を出力します。

このコードの重要な機能は、スリッページを最小限に抑えるためperformSelectorに、メソッドがメソッドのできるだけ早い段階で呼び出されることです。updateProgress

@interface ViewController ()
{
    CFTimeInterval progressStart;
    int progressCount;
}
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
@end

- (void)updateProgress
{
    if ( progressCount > 0 )
        [self performSelector:@selector(updateProgress) withObject:nil afterDelay:0.1];

    self.progressView.progress = progressCount / 15.0;
    NSLog( @"%2d %.3lf", progressCount, CACurrentMediaTime() - progressStart );
    progressCount--;
}

- (IBAction)someButtonPressed
{
    self.progressView.progress = 1.0;
    progressStart = CACurrentMediaTime();
    progressCount = 15;
    [self updateProgress];
}

そして、これが典型的な実行の結果です

2015-07-01 13:05:57.610 Progress[8354:907] 15 0.000
2015-07-01 13:05:57.711 Progress[8354:907] 14 0.101
2015-07-01 13:05:57.813 Progress[8354:907] 13 0.203
2015-07-01 13:05:57.914 Progress[8354:907] 12 0.304
2015-07-01 13:05:58.015 Progress[8354:907] 11 0.405
2015-07-01 13:05:58.116 Progress[8354:907] 10 0.506
2015-07-01 13:05:58.218 Progress[8354:907]  9 0.608
2015-07-01 13:05:58.319 Progress[8354:907]  8 0.709
2015-07-01 13:05:58.420 Progress[8354:907]  7 0.810
2015-07-01 13:05:58.520 Progress[8354:907]  6 0.910
2015-07-01 13:05:58.621 Progress[8354:907]  5 1.011
2015-07-01 13:05:58.722 Progress[8354:907]  4 1.112
2015-07-01 13:05:58.823 Progress[8354:907]  3 1.213
2015-07-01 13:05:58.924 Progress[8354:907]  2 1.314
2015-07-01 13:05:59.024 Progress[8354:907]  1 1.415
2015-07-01 13:05:59.125 Progress[8354:907]  0 1.515

このperformSelector:afterDelayメソッドには、各イベントで約 1 ミリ秒のずれがあることに注意してください。総ずれは 15 ミリ秒でした。デバイスの画面更新レートは 60 フレーム/秒、つまり 16.7 ミリ秒/フレームです。そのため、ずれの合計は 1 フレーム時間未満であり、ユーザーには気付かれません。

コメントで rmaddy が指摘したように、を使用するNSTimerと、ほとんどのスリッページを回避できます。ただし、最後のタイマー イベントは任意の時間だけずれることがあります。

于 2015-07-01T04:33:54.560 に答える