在这里,我有一些闭包强引用循环的示例。
如果我将一个闭包分配给一个存储属性,我可以使用闭包捕获列表使捕获的引用不可拥有或弱化。但是,如果我将一个方法分配给一个存储属性闭包或将该方法分配给外部范围内的闭包,则无法使用捕获列表。
我该如何消除最后两种情况中的引用循环?
仅使用闭包创建和避免强引用循环的示例
internal class ClosureClass {
internal let p1: String
internal lazy var p2: () -> String = {
[unowned self] // if you comment this out there is a strong reference cycle
() -> String in
return self.p1
}
internal init() {
self.p1 = "Default value of ClosureClass"
}
deinit {
print("Object with property '\(self.p1)' is being deinitialized")
}
}
print("Test 'Closure with strong reference to self':")
var cc: ClosureClass? = ClosureClass.init()
cc!.p2() // lazy need to call it once, else it will not be initiliazed
cc = nil
使用闭包从方法中创建强引用循环的示例
internal class MethodToClosureClass {
internal let p1: String
internal lazy var p2: () -> String = method(self) // Why not self.method ? Will create a strong reference cycle, but I can not set the reference to weak or unowned like in closures with the closure capture list
internal init() {
self.p1 = "Default value of MethodToClosureClass"
}
internal func method() -> String {
// [unowned self] in
return self.p1
}
deinit {
print("Object with property '\(self.p1)' is being deinitialized")
}
}
print("Test 'Set closure with method intern':")
var m2cc: MethodToClosureClass? = MethodToClosureClass.init()
m2cc!.p2() // lazy need to call it once, else it will not be initiliazed
m2cc = nil
使用从外部方法设置闭包创建强引用循环的示例
internal class MethodClass {
internal let p1: String
internal var p2: () -> String = {
return ""
}
internal init() {
self.p1 = "Default value of MethodClass"
}
internal func method() -> String {
// [unowned self] in
return self.p1
}
deinit {
print("Object with property '\(self.p1)' is being deinitialized")
}
}
print("Test 'Set closure with method extern':")
var mc: MethodClass? = MethodClass.init()
var method: () -> String = mc!.method // will create a strong reference
mc!.p2 = method
mc = nil
输出
测试“具有对self的强引用的闭包”:
拥有属性“ClosureClass的默认值”的对象正在被解除初始化。
测试“使用内部方法设置闭包”:
测试“使用外部方法设置闭包”:
self.method
而不是method(self)
。另外,您不需要将所有内容注释为 “internal”,因为这是默认值。 - Hamishself.
时不建议使用method
,这是缺少的功能还是bug,但当我写meth
时它给了我method(self)
的建议。感谢指出。有趣的是,method
对于外部作用域中的变量已经足够了,但对于属性来说却不够。 - Binarianself.method
而不是仅使用method
是lazy
属性的一个怪癖 - 它们需要显式地使用self.
,例如请参见此问答。 - Hamish