关于ARC的教程很多。但是由于引用捕获的变量如何变为空值,我无法理解无主或弱项的清晰工作。
Apple Document:
将闭包中的捕获定义为闭包时的无主引用 它捕获的实例将始终相互引用,并且将 总是在同一时间释放。
class RetainCycle {
var closure: (() -> Void)!
var string = "Hello"
init() {
closure = { [unowned self] in
self.string = "Hello, World!"
}
}
}
闭包在其主体内引用self(作为引用self.string的一种方式),闭包捕获self,这意味着它持有对RetainCycle实例的强引用。两者之间会建立一个强大的参考周期。凭空打破了其参考周期。
但是我想了解哪种情况不会同时相互解除,而Unown self变为null只是想使其崩溃。
答案 0 :(得分:1)
据我所知,您问closue运行时self如何为空。如果我做对了,我可以举一个我以前见过的非常相似的例子。
我为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
的{{1}}会发生什么情况。由于UIImageView
被释放而崩溃,但闭包仍然存在,并尝试到达其imageView
属性。就我所知,您想学习这一点。
我将image
的引用更改为unowned
,以解决此问题。
答案 1 :(得分:0)
这意味着它拥有对RetainCycle实例的强大引用
这不是事实。它具有对RetainCycle实例的无归属引用。这与强大的参考资料不一样。
但是我想了解哪种情况不会同时将它们相互释放,而无主自我变成零我只想崩溃。
任何时候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
。我们想要保留循环,以使该对象一直存在直到其完成处理程序运行为止,此时该块消失,对self
的引用消失,并且self
正确释放。因此,[weak self]
也不总是答案。