活动指标未出现

我有一些重型代码,运行时间约为0.2秒。

我设置了这样的活动指标; 然而,它没有显示,而是整个屏幕冻结大约0.2秒,直到代码完成。

func heavyWork() { self.actvityIndicator.startAnimating() ... // heavy loop codes here ... self.activityIndicator.stopAnimating() } 

这是使用活动指标的正确方法吗?

当我评论出来

 // self.activityIndicator.stopAnimating() 

活动指示器显示并保持在那里 – 代码设置正确。

但是UI似乎没有在适当的时候更新。

正如我所说,屏幕只是冻结而没有显示活动指示器,直到重型代码完成。

也许你想继续使用这样的模式:

 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在执行每行代码后都无法执行此操作。

因此,使用您的代码,当您告诉activityIndi​​cator startAnimating时,它告诉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()方法返回繁重工作的结果。 这是因为函数调度异步代码在不同的线程上运行然后立即返回,以便它可以继续当前的运行循环迭代。

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() } } } 

发生这种情况是因为您在主线程上运行重型代码。 通过这种方式,系统永远不会有机会提交图形事务,直到繁重的例程结束。 您的start和stop方法同时提交。
为了避免这种情况,你应该在另一个dispatch_queue上运行重载方法,但要注意大多数UIKit对象都不是线程安全的,应该在主队列上再次调度。