Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 活动指示器未出现_Ios_Swift_Activity Indicator - Fatal编程技术网

Ios 活动指示器未出现

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.

我有一些运行时间大约为0.2秒的繁重代码

我像这样设置活动指示器;但是,它不会显示,而是整个屏幕冻结约0.2秒,直到代码完成

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苦苦挣扎。