Swift UIActivityView stopAnimating()不起作用

时间:2017-10-17 23:42:45

标签: ios swift cocoa uiimageview uiactivityindicatorview

在我的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()的地方,指标实际上都停止了动画。这一点尤为令人困惑,因为我在调用之后立即停止它,但它仍然在那里。

1 个答案:

答案 0 :(得分:4)

您的代码存在一些问题。最大的一个是你使activityIndi​​cator成为一个计算属性。每次引用它时,都会执行关闭代码,并获得一个新的,从未见过的活动指示符。尝试将此代码作为测试:

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

请注意,每个print语句都有不同的地址。

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

相反,将变量设为惰性变量:

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

注意该代码如何具有赋值,并且闭包后面有括号(())。

延迟限定符意味着变量在第一次被引用之前不会被创建,然后只创建一次。

闭包后的parens表示闭包被调用为函数,变量activityIndicator将包含闭包的结果。

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