0

我已经实现了一个 UIProgressView 作为倒计时计时器,它的值在 1.5 秒内从 1.0 减少到 0.0。

它已经工作了,但问题是它花费的时间超过 1.5 秒,大约需要 2.0 - 2.5 秒,直到进度视图值达到 0.0

为了让它在 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

要动画进度,请在您的 reductionProgress 方法中尝试此代码

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

您尝试在 1.5 秒内更新进度视图 1000 次。这太快了,因为屏幕每秒只更新 60 次。换句话说,您在每次进度条在屏幕上实际重绘之间更新进度条超过 10 次。

相反,我建议以 0.1 秒为间隔进行 15 次更新,并且每次将进度条更改 1/15。

检查代码执行情况的一种方法是使用该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 毫秒/帧。所以总的滑点时间小于一帧时间,并且不会被用户注意到。

正如 rmaddy 在评论中指出的那样,使用 anNSTimer可以避免大部分滑点。但是,最后一个计时器事件仍可能会延迟任意时间。

于 2015-07-01T04:33:54.560 回答