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 秒进度动画。
简单的动画进度(有效但仍然有点跳跃)
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 任务,您的计时器将非常不准确地触发。我的第一个建议是这可能就是正在发生的事情。
这是一个例子:
- 你启动一个计时器,每秒做一些事情。
- 紧接着,您启动了一个较长的 运行ning 主线程任务(例如,您尝试将大量数据写入文件)。此任务需要五秒钟才能完成。
- 你的计时器想在一秒后触发,但你的文件写入是
在接下来的四秒钟内占用主线程,因此计时器无法触发
再等四秒钟。
如果是这种情况,那么要解决该问题,您要么需要将该主线程工作移至后台线程,要么想办法在 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
}
所以我使用 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 秒进度动画。
简单的动画进度(有效但仍然有点跳跃)
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 任务,您的计时器将非常不准确地触发。我的第一个建议是这可能就是正在发生的事情。
这是一个例子:
- 你启动一个计时器,每秒做一些事情。
- 紧接着,您启动了一个较长的 运行ning 主线程任务(例如,您尝试将大量数据写入文件)。此任务需要五秒钟才能完成。
- 你的计时器想在一秒后触发,但你的文件写入是 在接下来的四秒钟内占用主线程,因此计时器无法触发 再等四秒钟。
如果是这种情况,那么要解决该问题,您要么需要将该主线程工作移至后台线程,要么想办法在 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
}