class Person {
var hello : (() -> Void)?
var name = "name"
init() {
print("init \(self)")
}
deinit {
print("deinit \(self)")
}
}
var person : Person!
person = Person()
person.hello = { () -> Void in
print("\(person.name)")
}
person = nil
控制台输出是:
init Person
deinit Person
在我看来,因为'person'是一个可选的,所以Swift在'hello'闭包中保持弱引用,是吗?
答案 0 :(得分:2)
你没有得到一个保留周期,因为hello
闭包正在捕获一个变量,而不是一个常量,并且由于变量预计将来会改变,所以它不会保留它,它只是保持对它的引用。
将其转换为常量,您将获得预期的保留周期:
func test() {
let html = Person()
html.hello = { () -> Void in
print("\(html.name)")
}
}
test()
这仅打印init Person
,但是当函数结束时,html
超出范围并应该被释放。
如果您将变量定义为Objective-C
,则行为与__block
行为相同。
答案 1 :(得分:1)
因为html是可选的,所以你的闭包实际上是对enum(可选)的引用,而不是对象本身,所以只有一个对Person()的引用。
如果你创建了一个html实际超出范围的情况,那么就会有一个对Person()对象的延迟引用,因为捕获将是对html变量的唯一剩余引用。 但它仍然不是具有引用计数的Person()对象。
class Person {
var hello : (() -> Void)?
var name = "name"
init() {
print("init \(self)")
}
deinit {
print("deinit \(self)")
}
}
repeat
{
var html : Person
html = Person()
// this closure keep a reference to 'html'
html.hello = { () -> Void in
print("\(html.name)")
}
} while false