关闭中强,弱和无主自我解释
我需要一些关于Swift中关闭引用的解释。 这里是我使用的情况下,让我们想象,我们有:关闭中强,弱和无主自我解释
class A {...}
class B {
func makeAclosure() {
let instanceA = A()
instanceA.someFunctionA(completion: {(input) in
self.someAnotherFunction(input)
})
}
}
是否有A类和B或不之间的挡周期? 在这种情况下,它可能是一个保留周期?
因为不知道completion
是否为@escaping
(例如,如果它被保留),所以不可能说出A.someFunctionA
。对于其余的答案,我将假定它是@escaping
。
Swift需要确保运行时安全,并将保留未来可能需要的任何对象,在这种情况下,通过强烈参考self
(因为self
是封闭内部使用的唯一变量)。
在这种情况下没有参考周期。这是因为instanceA
不被保留,所以A => B,但乙!=> A.
但是,如果instanceA
被B
(假设您创建一个instanceA: A
属性,并将其设置),那么你将有一个保留保留周期。
为了解决这个问题,您可以在闭包中创建变量weak
或unowned
。他们都做同样的事情,但为你提供稍微不同的类型。它们都有一个弱引用,这意味着instanceA
将不会增加B
实例的引用计数;如果B
被解除分配,并且没有其他参考,instanceA
也被释放。
当使用[weak self]
self
是optional
,例如, self: B?
。然而,[unowned self]
明确展开,例如, self: B!
。这意味着如果关闭被调用,并且self
是nil
您的程序将崩溃。这就是为什么仅当使用unowned
时,如果确定释放B
也会释放A
,这一点很重要。有几种情况,其中unowned
是安全的,例如,在创建闭包并将其存储在创建它的同一个对象上的情况下,但是有更多的细微差别。
如果不确定,请使用weak
!
如果您的self
对象在调用闭包之前可能会被释放,您应该指定[weak self]
,这样可以避免错误的访问异常。
如果你知道它会绝对不会被收回,那么你可以使用[unowned self]
创建会像暗中展开可选的参考。
在您的例子中,B
实例拥有参考instanceA
(您makeAClosure()
功能的上下文中),所以你不会有保留周期结束。
您应该考虑执行someFunctionA(completion:)
,以确定在该封闭中是否需要unowned
或weak
对self
的引用。
(小题外话:如果你正在使用[weak self]
,然后以避免选项,例如self?
整个代码,你可以使用guard let `self` = self else { ... }
继续在封闭代码中使用self
这是错误的。在这种情况下,您不会有保留周期,因为常量instanceA在函数内部创建。 – Alex
谢谢你的回答!只是为了确认,所以当我在类B的函数内部创建一个instanceA:A时,它仅在函数的上下文中考虑,而不是该类的引用?做出强有力的参考的唯一方法是让instanceA:A类的属性? – Arrabidas92
@Alex哎呀!我将编辑答案以删除该部分。 其余的部分仍然有效,所以我会把它留在那里。 – royalmurder
谢谢你的回答!只是为了确认,所以当我在类B的函数内部创建一个instanceA:A时,它仅在函数的上下文中考虑,而不是该类的引用?做出强有力的参考的唯一方法是让instanceA:A类的属性?还有一个问题,如果我不把@escaping,封闭不保留自我? – Arrabidas92
是的,在这种情况下'instanceA'只保存在内存中,直到它不再被引用到任何地方,这是'makeAclosure'的一次执行完成。是的,停止'instanceA'被释放的唯一方法就是强烈引用它,比如将它设置为'B'的属性。如果你不放'@ escaping',编译器将不允许你存储传入的闭包。不用'@ escaping'开始,等待编译器发出抱怨! –