Ios 活动指示器未出现
我有一些运行时间大约为0.2秒的繁重代码 我像这样设置活动指示器;但是,它不会显示,而是整个屏幕冻结约0.2秒,直到代码完成Ios 活动指示器未出现,ios,swift,activity-indicator,Ios,Swift,Activity Indicator,我有一些运行时间大约为0.2秒的繁重代码 我像这样设置活动指示器;但是,它不会显示,而是整个屏幕冻结约0.2秒,直到代码完成 func heavyWork() { self.actvityIndicator.startAnimating() ... // heavy loop codes here ... self.activityIndicator.stopAnimating() } 这是使用活动指示器的正确方法吗 当我发表评论时 // self.
func heavyWork() {
self.actvityIndicator.startAnimating()
...
// heavy loop codes here
...
self.activityIndicator.stopAnimating()
}
这是使用活动指示器的正确方法吗
当我发表评论时
// self.activityIndicator.stopAnimating()
活动指示灯显示并保持不变-代码设置正确
但用户界面似乎没有及时更新
正如我所说,在重载代码完成之前,屏幕只是冻结而不显示活动指示器。这是因为您正在主线程上运行重载代码。这样,在繁重的例程结束之前,系统永远不会有机会提交图形事务。同时提交启动和停止方法。
为了避免在另一个
调度队列上运行重载方法,请注意大多数UIKit对象不是线程安全的,应该在主队列上再次调度。也许您希望使用这种模式:
func heavyWork() {
self.actvityIndicator.startAnimating()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
// ...
// heavy loop codes here
// ...
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.activityIndicator.stopAnimating()
})
});
}
因为繁重的工作应该在后台线程中进行,并且您需要在之后在主线程上更新UI
注意:显然,假设您在主线程上调用func heavyWork()
;如果没有,您可能还需要将初始UI更新转移到主线程。如果您希望应用程序在执行一些繁重任务时能够响应,则需要在后台线程上执行
这大致就是这里发生的事情:应用程序的主线程在运行循环中执行。在每个循环迭代开始时,iOS检查任何事件(例如用户交互、由于动画而改变的视图、触发的计时器等),然后将一组要执行的方法排队。然后,iOS开始执行这些方法中的每一种,然后,一旦一切完成,它就会更新显示。然后开始下一次运行循环迭代。更新显示的成本很高,因此iOS无法在每行代码执行后进行更新
因此,在代码中,当您告诉activityIndicator开始动画时,它会告诉iOS在每次运行循环迭代结束时,需要将activityIndicator图像更新为动画序列中的下一个图像。然后,在iOS到达当前运行循环迭代的末尾之前,您将调用stopAnimating,它告诉iOS不再需要更新图像。所以基本上你告诉它在它开始之前就停止
您可以使用grandcentraldispatch在不同的线程上轻松运行代码。但是需要注意的是,对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()方法返回繁重工作的结果。这是因为函数安排异步代码在不同的线程上运行,然后立即返回,以便继续当前的运行循环迭代
SWIFT 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()
}
}
}
SWIFT 4:
func heavyWork() {
self.actvityIndicator.startAnimating()
DispatchQueue.global(qos: .background).async {
// ...
// heavy loop codes here
// ...
DispatchQueue.main.async {
self.actvityIndicator.stopAnimating()
}
}
}
您的重循环代码是否在后台线程上运行?重循环代码将阻止UI显示活动指示器。此外,如果您在后台线程上调用heavyWork
,UI
不应更新,因为它不在主线程上。如果您在后台线程上,则无法修改UI上的任何内容;如果你是在主线程,那么这不是最好的做繁重的工作。请感谢这个答案!我一整天都在为DispatchQueue和activity indicator苦苦挣扎。