如果您希望应用程序在执行一些繁重的任务时响应,您将需要在后台线程上执行它。
这大致是这里发生的事情:您的应用程序的主线程在运行循环中执行。在每个循环迭代开始时,iOS 会检查任何事件(例如用户交互、由于动画而改变的视图、触发计时器等),然后将一堆方法排队等待执行。iOS 然后去执行这些方法中的每一个,然后,一旦一切都完成,它会更新显示。然后下一个运行循环迭代开始。更新显示的成本很高,因此 iOS 无法在执行完每一行代码后进行。
因此,使用您的代码,当您告诉 activityIndicator 开始动画时,它会告诉 iOS 在每次运行循环迭代结束时,活动指示器图像需要更新为动画序列中的下一个图像。然后,在 iOS 到达当前运行循环迭代的末尾之前,您将调用 stopAnimating 来告诉 iOS 它不再需要更新图像。所以基本上你告诉它在它开始之前停止。
您可以使用 Grand Central Dispatch 在不同的线程上轻松运行代码。但是需要注意的是,对 UI 的任何更新都必须在主线程上完成。
func heavyWork() {
self.activityIndicator.startAnimating()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
// Do heavy work here
dispatch_async(dispatch_get_main_queue()) {
// UI updates must be on main thread
self.activityIndicator.stopAnimating()
}
}
}
另请注意,在异步编程时,例如在上面的示例中,您不能从调用它的方法中的异步部分返回值。例如,在上面的示例中,您不能从 heavyWork() 方法返回繁重工作的结果。这是因为该函数将异步代码安排在不同的线程上运行,然后立即返回,这样它就可以继续当前的运行循环迭代。
斯威夫特 4
func heavyWork() {
activityIndicator.startAnimating()
DispatchQueue.global(qos: .default).async {
// Do heavy work here
DispatchQueue.main.async { [weak self] in
// UI updates must be on main thread
self?.activityIndicator.stopAnimating()
}
}
}