我们总是在Swift中使用[unowned self]内部封闭 [英] Shall we always use [unowned self] inside closure in Swift
问题描述
在WWDC 2014会议403 。一个强大的参考周期是当存在一个所有权循环,其中对象最终彼此拥有(可能通过第三方),因此它们将永远不会被释放,因为它们都确保彼此坚持。
在闭包的特定情况下,您只需要意识到在其中引用的任何变量都由闭包拥有。只要封闭物周围,这些物体就可以保证在周围。阻止该所有权的唯一方法是执行 [无主自我]
或 [弱自我]
。因此,如果一个类拥有一个闭包,并且该闭包捕获了对该类的强引用,那么闭包和类之间就有一个强大的引用循环。这还包括如果该类拥有拥有该闭包的东西。
特别是在视频的示例中
在幻灯片上的示例中, TempNotifier
通过 onChange
成员变量拥有闭包。如果他们没有将 self
声明为无主
,那么关闭也将拥有 self
创建一个强大的参考周期。
无主
和弱
无主
和弱$ c之间的差异$ c>是
弱
被声明为可选,而无主
则不是。通过声明它 weak
,您可以处理在某些时候它可能在闭包内部为零的情况。如果您尝试访问恰好为nil的无主
变量,则会导致整个程序崩溃。所以只有当你肯定变量总是存在时,才会使用无主
,而闭包是在
In WWDC 2014 session 403 Intermediate Swift and transcript, there was the following slide
The speaker said in that case, if we don't use [unowned self]
there, it will be a memory leak. Does it mean we should always use [unowned self]
inside closure?
On line 64 of ViewController.swift of the Swift Weather app, I don't use [unowned self]
. But I update the UI by using some @IBOutlet
s like self.temperature
and self.loadingIndicator
. It may be OK because all @IBOutlet
s I defined are weak
. But for safety, should we always use [unowned self]
?
class TempNotifier {
var onChange: (Int) -> Void = {_ in }
var currentTemp = 72
init() {
onChange = { [unowned self] temp in
self.currentTemp = temp
}
}
}
No, there are definitely times where you would not want to use [unowned self]
. Sometimes you want the closure to capture self in order to make sure that it is still around by the time the closure is called.
Example: Making an asynchronous network request
If you are making an asynchronous network request you do want the closure to retain self
for when the request finishes. That object may have otherwise been deallocated but you still want to be able to handle the request finishing.
When to use unowned self
or weak self
The only time where you really want to use [unowned self]
or [weak self]
is when you would create a strong reference cycle. A strong reference cycle is when there is a loop of ownership where objects end up owning each other (maybe through a third party) and therefore they will never be deallocated because they are both ensuring that each other stick around.
In the specific case of a closure, you just need to realize that any variable that is referenced inside of it, gets "owned" by the closure. As long as the closure is around, those objects are guaranteed to be around. The only way to stop that ownership, is to do the [unowned self]
or [weak self]
. So if a class owns a closure, and that closure captures a strong reference to that class, then you have a strong reference cycle between the closure and the class. This also includes if the class owns something that owns the closure.
Specifically in the example from the video
In the example on the slide, TempNotifier
owns the closure through the onChange
member variable. If they did not declare self
as unowned
, the closure would also own self
creating a strong reference cycle.
Difference between unowned
and weak
The difference between unowned
and weak
is that weak
is declared as an Optional while unowned
is not. By declaring it weak
you get to handle the case that it might be nil inside the closure at some point. If you try to access an unowned
variable that happens to be nil, it will crash the whole program. So only use unowned
when you are positive that variable will always be around while the closure is around
这篇关于我们总是在Swift中使用[unowned self]内部封闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!