Swift - UIProgressView 使用 NSTimer 时不流畅

Swift - UIProgressView is not smooth with NSTimer

所以我使用 NSTimer 让用户知道应用程序正在运行。进度条设置为持续 3 秒,但是当 运行 时,它显示为 'ticking' 运动并且没有应有的平滑。无论如何我可以让它更平滑 - 我确定这只是我的计算错误....

如果有人能看一下那就太好了。这是代码:

import UIKit

class LoadingScreen: UIViewController {


    var time : Float = 0.0
    var timer: NSTimer?

    @IBOutlet weak var progressView: UIProgressView!


    override func viewDidLoad() {
        super.viewDidLoad()

// Do stuff

timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector:Selector("setProgress"), userInfo: nil, repeats: true)

}//close viewDidLoad

  func setProgress() {
        time += 0.1
        progressView.progress = time / 3
        if time >= 3 {
            timer!.invalidate()
        }
    }

}

编辑:一个简单的 3 秒 UIView 动画(推荐)

如果您的栏只是平稳移动以指示 activity,可以考虑使用 UIActivityIndicatorView 或自定义 UIView 动画:

override func viewDidAppear(animated: Bool)
{
    super.viewDidAppear(animated)

    UIView.animateWithDuration(3, animations: { () -> Void in
        self.progressView.setProgress(1.0, animated: true)
    })
}

首先确保您的 progressView 的进度设置为零。这将产生流畅的 3 秒进度动画。

简单的动画进度(有效但仍然有点跳跃)

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIProgressView_Class/#//apple_ref/occ/instm/UIProgressView/setProgress:animated:

func setProgress() {
    time += 0.1
    progressView.setProgress(time / 3, animated: true)
    if time >= 3 {
        timer!.invalidate()
    }
}

间隔较小的选项。 (不推荐)

将您的计时器设置为更小的间隔:

timer = NSTimer.scheduledTimerWithTimeInterval(0.001, target: self, selector:Selector("setProgress"), userInfo: nil, repeats: true)

然后更新你的函数

func setProgress() {
    time += 0.001
    progressView.setProgress(time / 3, animated: true)
    if time >= 3 {
        timer!.invalidate()
    }
}

很难说到底是什么问题。如果您在 setProgress 中放置打印行以打印时间戳,我想查看输出。它实际上是每十分之一秒触发一次吗?我的猜测是它不是。

为什么不呢?嗯,定时器在主线程中调度了一个运行循环任务来执行setProgress中的代码。该任务不能 运行 直到队列中它前面的任务完成。因此,如果您的主线程中发生了很长的 运行ning 任务,您的计时器将非常不准确地触发。我的第一个建议是这可能就是正在发生的事情。

这是一个例子:

  1. 你启动一个计时器,每秒做一些事情。
  2. 紧接着,您启动了一个较长的 运行ning 主线程任务(例如,您尝试将大量数据写入文件)。此任务需要五秒钟才能完成。
  3. 你的计时器想在一秒后触发,但你的文件写入是 在接下来的四秒钟内占用主线程,因此计时器无法触发 再等四秒钟。

如果是这种情况,那么要解决该问题,您要么需要将该主线程工作移至后台线程,要么想办法在 return 转到 运行 周期性循环。例如,在你的 运行ning 主线程运行期间,你可以在你的 运行 循环中定期调用 runUntilDate 让其他 运行 循环任务执行。

请注意,在 运行 宁主线程任务期间,您不能只是定期增加进度条填充,因为在您 return 运行 循环。

动画变化的正确方法:animateWithDuration:animations: or CABasicAnimation。您可以使用它来创建流畅的动画

继续加载程序

timer = Timer.scheduledTimer(timeInterval: 0.001, target: self, selector: #selector(setProgress), userInfo: nil, repeats: true)

func setProgress() {
        time += 0.001
        downloadProgressBar.setProgress(time / 3, animated: true)
        if time >= 3 {
            self.time = 0.001
            downloadProgressBar.progress = 0
            let color = self.downloadProgressBar.progressTintColor
            self.downloadProgressBar.progressTintColor = self.downloadProgressBar.trackTintColor
            self.downloadProgressBar.trackTintColor = color
        }