为什么在依赖于存在self的块中指定[unowned self]?
为什么在依赖于存在self的块中指定[unowned self]?
我希望self不是nil,并且我确信在执行块期间它不会是nil。那么为什么要明确指定[unowned self]?
object.executeBlock {
date = self.lastModified
}
与
object.executeBlock { [unowned self] in
date = self.lastModified
}
编辑:
好吧,我得到了一些负面评价,所以让我们再试一次。问:假设我有一个问题。这个问题是我想要防止引用循环。我有两个选择。我可以使用[unowned self]或者我可以使用[weak self]。因此,我的问题是:从这两个选择中,为什么我要选择[unowned self]?为什么不总是选择[weak self]?
在Swift中,我们经常使用闭包来处理异步任务或者作为回调函数。在闭包中,我们可能会引用到包含该闭包的对象(通常是self),这样就会产生一个循环引用的问题。为了解决这个问题,Swift提供了弱引用和无主引用两种方式。
弱引用使用weak关键字来声明,它允许闭包中引用的对象可以被释放。当闭包需要引用的对象可能为nil时,我们就需要使用弱引用。
无主引用使用unowned关键字来声明,它也允许闭包中引用的对象可以被释放。但是与弱引用不同的是,无主引用假设引用的对象在闭包执行期间不会被释放,所以它不会被自动设置为nil。如果在闭包执行期间引用的对象被释放了,那么使用无主引用将会导致程序崩溃。
在上述引用的文章中,指出了在闭包中使用[unowned self]的原因和解决方法。根据文章的解释,使用[unowned self]将self声明为一个隐式解包的可选值。这样做的好处是不需要我们手动进行解包操作,但是如果self实际上为nil的话,就会导致程序崩溃。
那么为什么要在闭包中使用[unowned self]呢?原因在于当闭包和包含它的对象同时被释放时,我们希望避免在即将dealloc的对象中安全地将弱引用置为nil的开销。因为在对象即将被释放的时候,我们可以确保闭包不会再被执行,所以使用[unowned self]可以避免额外的开销。
解决方法就是在闭包中使用[unowned self]而不是weak关键字。这样做的前提是我们能够确保在闭包执行期间,引用的对象不会被释放。如果无法确定引用的对象是否会被释放,那么还是应该使用weak关键字来声明引用。
总结起来,使用[unowned self]可以避免在即将dealloc的对象中安全地将弱引用置为nil的开销,但是需要确保在闭包执行期间引用的对象不会被释放。
在闭包中使用[unowned self]的原因是为了指定闭包中的self不会为nil。解决方法是使用[weak self]来避免self为nil的情况。如果在使用[unowned self]时发生崩溃,那么很可能是闭包中的self在某个时刻为nil,这就是为什么你必须改用[weak self]的原因。
在闭包中使用strong、weak和unowned是非常重要的,以下是来自手册的相关部分:https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/AutomaticReferenceCounting.html
在代码中使用[unowned self]
或[weak self]
的唯一时机是当你需要避免strong reference cycle(强引用循环)的情况下。强引用循环是指存在一种所有权循环的情况,其中对象相互拥有对方(可能通过第三方对象),因此它们将永远不会被释放,因为它们彼此都确保对方存在。
那里有一个强引用循环吗?
嗨,Arsen,谢谢你的回复。但恐怕这并没有完全回答我的问题。类似的问题可以在这里找到,该问题的答案也未能真正回答“为什么使用unowned self”的问题。我只想知道什么情况下我需要使用'unowned self'而不是'weak self'。这里的答案指出,如果我们使用weak,那么self就是一个可选项。我可以接受这个解释...但是为什么要使用unowned self呢?特别地,只是unowned self。
:你的问题并没有讨论unowned
与weak
之间的区别。你的问题是关于unowned
与没有任何修饰符的情况,而这个答案回答了你的问题。至于为什么选择unowned
而不是weak
,答案是你也可以使用weak self
,但是这样self
将变为可选项,你需要进行解包,而如果你知道self
仍然存活,unowned self
更加方便,因为self
是非可选类型,所以你可以直接使用它而不需要显式解包。