Swift UIActivityView stopAnimating() 不工作

Swift UIActivityView stopAnimating() not working

在我的 UIImageView 子类中,我有一个 UIActivityIndicatorView 和一个下载图像的函数,定义如下:

class FooUIImageView: UIImageView {

        var activityIndicator: UIActivityIndicatorView {
            let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .white)
            activityIndicator.hidesWhenStopped = true
            activityIndicator.center = CGPoint(x: self.frame.width/2, y: self.frame.height/2)
            self.addSubview(activityIndicator)
            return activityIndicator
        }

        func downloadImageFrom(url: URL, imageMode: UIViewContentMode) {

            self.activityIndicator.startAnimating()
            self.activityIndicator.stopAnimating()

            contentMode = imageMode
            if let cachedImage = imageCache.object(forKey: url.absoluteString as NSString) as? UIImage {
                self.image = cachedImage
            } else {
                URLSession.shared.dataTask(with: url) { data, _, error in
                    guard let data = data, error == nil else { return }
                        DispatchQueue.main.async {
                            if let imageToCache = UIImage(data: data) {
                                self.activityIndicator.stopAnimating()
                                self.imageCache.setObject(imageToCache, forKey: url.absoluteString as NSString)
                                self.image = imageToCache
                            } else {
                                self.activityIndicator.stopAnimating()
                                self.image = nil
                            }
                        }
                }.resume()
            }

            activityIndicator.stopAnimating()
       }
}

当 运行 我的应用程序时,activityIndicator 开始加载 - 然后最终显示图像。然而,activityIndicator 仍然在屏幕上并且永远不会消失。在上面我调用 stopAnimating() 的地方的 none 中,指示器实际上停止了动画。这特别令人困惑,我在调用它后立即停止它但它仍然存在。

您的代码存在一些问题。最重要的是您已将 activityIndicator 设为计算 属性。每次您引用它时,您的关闭代码都会被执行,您会得到一个新的、前所未见的 activity 指标。试试这个代码作为测试:

print(String(format: "activityIndicator address = %X", activityIndicator))
print(String(format: "activityIndicator address = %X", activityIndicator))
print(String(format: "activityIndicator address = %X", activityIndicator))

请注意,每个打印语句的地址都不同。

这意味着每次引用 activityIndicatorself.activityIndicator 时,您都会创建另一个 activity 指标并将其添加到视图层次结构中。这不是你想要的。

相反,让你的变量成为惰性变量:

lazy var activityIndicator: UIActivityIndicatorView = {
    let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .white)
    activityIndicator.hidesWhenStopped = true
    activityIndicator.center = CGPoint(x: self.frame.width/2, y: self.frame.height/2)
    self.addSubview(activityIndicator)
    return activityIndicator
}()

请注意该代码是如何进行赋值的,并且闭包的后缀有括号 (())。

惰性限定符意味着变量直到第一次被引用时才被创建,然后只被创建一次。

闭包后面的括号表示闭包像函数一样被调用,变量 activityIndicator 将包含闭包的结果。

您还应该摆脱所有地方的 stopAnimating() 调用,但在 dataTask 的完成处理程序中对 DispatchQueue.main.async 的调用除外。您只想在下载完成后停止动画,并且您必须像从主线程那样进行 UI 调用。对 stopAnimating() 的额外调用只会给您带来麻烦。