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))
请注意,每个打印语句的地址都不同。
这意味着每次引用 activityIndicator
或 self.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()
的额外调用只会给您带来麻烦。
在我的 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))
请注意,每个打印语句的地址都不同。
这意味着每次引用 activityIndicator
或 self.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()
的额外调用只会给您带来麻烦。