我试图让进度条充当计时器并从15秒倒计时,这是我的代码:
private var timer: dispatch_source_t!
private var timeRemaining: Double = 15
override public func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
profilePicture.layer.cornerRadius = profilePicture.bounds.width / 2
let queue = dispatch_queue_create("buzz.qualify.client.timer", nil)
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue)
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 10 * NSEC_PER_MSEC, 5 * NSEC_PER_MSEC)
dispatch_source_set_event_handler(timer) {
self.timeRemaining -= 0.01;
self.timerBar.setProgress(Float(self.timeRemaining) / 15.0, animated: true)
print(String(self.timerBar.progress))
}
dispatch_resume(timer)
}
print()打印正确的结果,但进度条永远不会更新,有时它会在12-15%左右完成一次更新,只有JUMP然后再做其他事情。
如何使此栏稳定地向下流动,然后在计时器结束时执行任务而不阻止UI线程。
答案 0 :(得分:6)
在siburb的回答中,他正确地指出应该确保在主线程上发生UI更新。
但是我有一个次要的观察,即你每秒进行100次更新,并且没有必要这么做,因为最大屏幕刷新率是每秒60帧。
然而,显示链接就像一个计时器,除了它链接到屏幕刷新率。你可以这样做:
var displayLink: CADisplayLink?
var startTime: CFAbsoluteTime?
let duration = 15.0
func startDisplayLink() {
startTime = CFAbsoluteTimeGetCurrent()
displayLink = CADisplayLink(target: self, selector: "handleDisplayLink:")
displayLink?.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
}
func stopDisplayLink() {
displayLink?.invalidate()
displayLink = nil
}
func handleDisplayLink(displayLink: CADisplayLink) {
let percentComplete = Float((CFAbsoluteTimeGetCurrent() - startTime!) / duration)
if percentComplete < 1.0 {
self.timerBar.setProgress(1.0 - percentComplete, animated: false)
} else {
stopDisplayLink()
self.timerBar.setProgress(0.0, animated: false)
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
startDisplayLink()
}
或者,如果你在后台线程上做某事想要比UIProgressView
发布更新比主线程可以为它们服务更快,那么我会使用调度源将其发布到主线程输入DISPATCH_SOURCE_TYPE_DATA_ADD
。
但是,如果你只是想在一段固定的时间内更新进度视图,那么显示链接可能比定时器更好。
答案 1 :(得分:2)
您必须始终更新主线程上的UI。我不是Swift专家,但看起来你正在尝试在后台更新UIProgressView
。
尝试更新主队列上的UIProgressView
,如下所示:
dispatch_async(dispatch_get_main_queue(),^{
self.timerBar.setProgress(Float(self.timeRemaining) / 15.0, animated: true)
print(String(self.timerBar.progress))
})