有很多关于ARC的教程。但我不理解无主或弱的明确工作,因为引用捕获的变量如何变为空。
Apple文件:
当闭包和它捕获的实例将始终相互引用时,将闭包中的捕获定义为无主引用,并且将始终同时取消分配。
class RetainCycle {
var closure: (() -> Void)!
var string = "Hello"
init() {
closure = { [unowned self] in
self.string = "Hello, World!"
}
}
}
闭包引用其身体内的self(作为引用self.string的一种方式),闭包捕获self,这意味着它拥有一个强大的引用返回到RetainCycle实例。在两者之间创建了强大的参考周期。通过无主的破坏参考周期。
但我想了解哪个场景不会同时被相互解除分配而且无主自我变为空只想要崩溃它。
在我得到的时候,你问在关闭运行时self是如何为null。如果我做对了,我可以给你一个与我之前见过的相似的例子。
我写了一个UIImageView的扩展,从给定的链接下载图像,并像这样设置自己。
public extension UIImageView{
func downloadImage(link: String){
let url = URL(string:link)
URLSession.shared.dataTask(with: url){ [unowned self]
if let image = UIImage(data: data){
DispatchQueue.main.async{
self.image = image
}
}
}
task.start()
}
}
但有一个问题。下载图像是后台任务。我将完成方法设置为UrlSession并增加其引用计数。所以,即使imageView被解除了,我的闭包仍然存在。
那么如果我在下载完成之前关闭我的viewController
并保存我的UIImageView
会发生什么。它崩溃是因为imageView
被解除分配但封闭仍然存在并试图达到其image
财产。我得到了,你想学习这个。
我改变了unowned
对weak
的引用来解决这个问题。
这意味着它拥有一个强大的引用回到RetainCycle实例
事实并非如此。它有一个无主的引用返回到RetainCycle实例。这与强有力的参考不同。
但是我想知道哪个场景不会同时被相互解除分配而且无主的自我变成了nilI只是想让它崩溃。
任何时候closure
被RetainCycle
以外的东西捕获,并且比其所有者更长寿:
var rc: RetainCycle? = RetainCycle() // create an RC
let cl = rc?.closure // Hold onto its closure
rc = nil // Deallocate the RC
cl?() // Access the closure safely, but its reference to `self` is invalid. Crash.
作为一项规则,涉及unowned self
的封闭应该不可能在self
之外引用。有时很难知道这是真的。例如,这是一个最近崩溃了我正在处理的应用程序的案例:
var completion: (() -> Void)?
...
DispatchQueue.main.async { [unowned self] in
self.completion()
self.completion = nil
}
这感觉很好,但是如果self
在排队主队列块和块运行的时间之间被解除分配,那就是繁荣。
顺便说一句,在这种情况下,正确答案将是一个规则的,强大的self
。我们希望retain循环保持这个对象,直到它的完成处理程序运行,此时块消失,对self
的引用消失,并且self
被正确释放。所以[weak self]
也不总是答案。