当我们将一个对象的实例作为参数传递给一个方法时,该方法是在该对象内部定义的,如下面的代码所示,它会创建一个保留循环吗?
self.someMethod(self)
最佳答案
如果您引用类的实例方法:
class FooBar {
func foo() {
print("Foo")
}
func bar() {
self.foo()
}
}
“self”是隐含的,编译器不需要它。即使您在没有 self.
的情况下使用 foo()
,它仍然会隐式引用 self。
不,没有保留周期,因为您是在同一对象上从一个实例方法调用另一个实例方法。
编辑:
self 给您带来麻烦的地方在于“转义”闭包。转义闭包是传递给另一个对象的闭包,该对象对其进行强引用。完成处理程序通常会转义闭包。
因此,当您调用一个接受完成处理程序的函数并且该完成处理程序是一个转义闭包时,另一个对象将获得闭包的所有权。
现在,如果闭包使用 self,则意味着闭包也拥有“self”
typealias completionHandler = () -> ()
class AClass {
lazy var someOtherObject = SomeOtherObject()
var value: Int = 0
func callClosure() {
someOtherObject.doSomething(completion: {
self.foo = self.foo + 1
}
}
}
class SomeOtherObject {
var myCompletionHandler: () -> ()
func doSomething( completion: @escaping completionHandler) {
myCompletionHandler = completion
//pretend there is code here to call an async method and invoke completion
}
}
上面对 self 的使用确实导致了一个保留周期。方法如下:
AClass
的实例创建一个类型为 SomeOtherObject
的对象,并保持对它的强/拥有引用。只要 AClass
的实例存在,SomeOtherObject
就不会消失。
当我们调用callClosure()
时,我们传入一个完成处理程序。 SomeOtherObject 取得闭包的所有权。
现在,由于闭包的代码引用了 self
,因此闭包获得了 self
的所有权。我们现在在拥有 SomeOtherObject
的 AClass 对象、拥有闭包的 SomeOtherObject
和拥有 的闭包之间有一个三向保留循环>AClass
对象。
您可以通过向闭包添加“捕获列表”来修复保留周期。这是闭包使用的变量列表,应该保持弱。修改后的代码可能如下所示:
func callClosure() {
//the `[weak self]` capture list below makes self weak inside the closure
someOtherObject.doSomething(completion: { [weak self] in
///use a guard to map weakSelf to strongSelf if it isn't nil, or return
//if self has been deallocated and is now nil.
guard let strongSelf = weakSelf else { return }
strongSelf.foo = strongSelf.foo + 1
}
}
关于swift - 将 self 作为参数传递给方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49633208/