UIProgressView 和定期刷新(Swift)
UIProgressView and regular refresh (in Swift)
我需要解析大量文本,并希望在此过程中向用户提供一些反馈。
环境是 Swift,虽然我确实在 Obj-C 中看到了一些代码([self performSelector:@selector(.....)),但它没有多大意义。如果我知道如何将其嵌入到 Swift 方法中,我会这样做。
我可以用一个给出相同结果的可重现的小案例来总结这个问题。即在一个循环中,增加一个值,显示进度并返回直到完成。显然,不会显示进度,因为 iOS 会等到循环完成后再刷新屏幕。
这确实有道理,所以我想在不同的时间间隔中断处理(即循环)并在继续处理之前刷新进度条。
我当前的代码如下所示:
@IBAction func goButton(sender: UIButton) {
currentCounter = 0
target = textTarget.text.toInt()!
step = textStep.text.toInt()!
updateProgressBar()
while currentCounter < target {
currentCounter += step
updateProgressBar()
}
}
func updateProgressBar() {
var percentage = Float(currentCounter) / Float(target) * 100
progressPercentage.text = "\(percentage) %"
println("progress = \(percentage)")
progressBar.setProgress(percentage, animated: false)
}
我看过以下内容:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
// do some task here...
}
dispatch_async(dispatch_get_main_queue()) {
// do another task here...
}
我如何使用这种方法(如果相关),如果我这样做,处理与刷新调用的区别在哪里?
乔恩
GCD (Grand Central Dispatch) 绝对是更好的选择。它简单、强大且使用起来直观,尽管一开始语法可能有不同的建议。
在进行耗时工作时更新 UI 的方法的要点始终是:
- 您的应用 运行 在主队列中
- 在某些时候你想做一些耗时的工作,所以将工作发送到主队列以外的某个队列。将
dispatch_async
与主队列以外的队列一起使用(您可以使用内置队列,也可以创建自己的队列)
- 里面那个耗时的工作要更新 UI。 UI应该总是在主队列中更新,所以从那个时间-消耗的工作,你做另一个
dispatch_async
,这次使用主队列(有一种方法可以访问主队列)。
- 在那个内部
dispatch_async
中,您更新 UI。
有关在 Swift 上下文中使用 GCD 的不错且全面的教程,请查看 this。
这是一个更新的代码答案,因为我认为其他人将从该模式中受益:
@IBAction func goButton(sender: UIButton) {
target = textTarget.text.toInt()!
step = textStep.text.toInt()!
currentCounter = 0
updateProgressBar()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
self.doTimeConsumingWork()
}
}
func doTimeConsumingWork() {
while currentCounter < target {
currentCounter += step
percentage = Float(currentCounter) / Float(target) * 100
if (percentage > 0.0) && (percentage % 10.0) == 0.0 {
// This is the important bit :)
// I chose to do this synchronously (not async) since progress updating can actually be done quite a while after the time consuming work is over
dispatch_sync(dispatch_get_main_queue()) {
self.updateProgressBar()
}
}
}
println("Finished doing time consuming work")
}
func updateProgressBar() {
progressPercentage.text = "\(percentage) %"
println("target = \(target), step = \(step) progress = \(percentage)")
progressBar.setProgress(percentage / 100.0, animated: false)
}
我需要解析大量文本,并希望在此过程中向用户提供一些反馈。
环境是 Swift,虽然我确实在 Obj-C 中看到了一些代码([self performSelector:@selector(.....)),但它没有多大意义。如果我知道如何将其嵌入到 Swift 方法中,我会这样做。
我可以用一个给出相同结果的可重现的小案例来总结这个问题。即在一个循环中,增加一个值,显示进度并返回直到完成。显然,不会显示进度,因为 iOS 会等到循环完成后再刷新屏幕。
这确实有道理,所以我想在不同的时间间隔中断处理(即循环)并在继续处理之前刷新进度条。
我当前的代码如下所示:
@IBAction func goButton(sender: UIButton) {
currentCounter = 0
target = textTarget.text.toInt()!
step = textStep.text.toInt()!
updateProgressBar()
while currentCounter < target {
currentCounter += step
updateProgressBar()
}
}
func updateProgressBar() {
var percentage = Float(currentCounter) / Float(target) * 100
progressPercentage.text = "\(percentage) %"
println("progress = \(percentage)")
progressBar.setProgress(percentage, animated: false)
}
我看过以下内容:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
// do some task here...
}
dispatch_async(dispatch_get_main_queue()) {
// do another task here...
}
我如何使用这种方法(如果相关),如果我这样做,处理与刷新调用的区别在哪里?
乔恩
GCD (Grand Central Dispatch) 绝对是更好的选择。它简单、强大且使用起来直观,尽管一开始语法可能有不同的建议。
在进行耗时工作时更新 UI 的方法的要点始终是:
- 您的应用 运行 在主队列中
- 在某些时候你想做一些耗时的工作,所以将工作发送到主队列以外的某个队列。将
dispatch_async
与主队列以外的队列一起使用(您可以使用内置队列,也可以创建自己的队列) - 里面那个耗时的工作要更新 UI。 UI应该总是在主队列中更新,所以从那个时间-消耗的工作,你做另一个
dispatch_async
,这次使用主队列(有一种方法可以访问主队列)。 - 在那个内部
dispatch_async
中,您更新 UI。
有关在 Swift 上下文中使用 GCD 的不错且全面的教程,请查看 this。
这是一个更新的代码答案,因为我认为其他人将从该模式中受益:
@IBAction func goButton(sender: UIButton) {
target = textTarget.text.toInt()!
step = textStep.text.toInt()!
currentCounter = 0
updateProgressBar()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
self.doTimeConsumingWork()
}
}
func doTimeConsumingWork() {
while currentCounter < target {
currentCounter += step
percentage = Float(currentCounter) / Float(target) * 100
if (percentage > 0.0) && (percentage % 10.0) == 0.0 {
// This is the important bit :)
// I chose to do this synchronously (not async) since progress updating can actually be done quite a while after the time consuming work is over
dispatch_sync(dispatch_get_main_queue()) {
self.updateProgressBar()
}
}
}
println("Finished doing time consuming work")
}
func updateProgressBar() {
progressPercentage.text = "\(percentage) %"
println("target = \(target), step = \(step) progress = \(percentage)")
progressBar.setProgress(percentage / 100.0, animated: false)
}