Apple Swift 语言官方指南中的代码如下:
class HTMLElement {
let name: String
let text: String?
@lazy var asHTML: () -> String = {
[unowned self] in
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
println("\(name) is being deinitialized.")
}
}
在闭包中使用带有unowned
的捕获列表以避免保留循环。我们演示一下:
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "Hello, world!")
println(paragraph!.asHTML())
paragraph = nil
结果应该是
<p>Hello, world!</p>
p is being deinitialized.
最后一行很重要,因为它告诉我们paragraph
按预期被取消初始化,但实际结果是
<p>Hello, world!</p>
最后一行没有出现。内存泄露了。这是官方指南中的原始代码。unowned
无法正常工作?
因此,我使用 weak
而不是 unowned
来测试会发生什么:
...
@lazy var asHTML: () -> String = {
[weak self] in
if let text = self?.text {
return "<\(self?.name)>\(text)</\(self?.name)>"
} else {
return "<\(self?.name) />"
}
}
...
结果正是我们想要的。控制台显示p is being deinitialized.
我不明白我出了什么问题,还是指南中的原始代码出错了,还是其他原因?
最佳答案
编辑:此问题现已在 xcode 6 beta 3 中修复:
• unowned class references will no longer sometimes retain their target. (16980445)
在昨天发布的 Xcode 6 beta 2 发行说明中,提到:
• unowned class references sometimes retain their target. (16980445)
Xcode 6 Beta 2 中的已知问题。
关于closures - 为什么闭包中的 "unowned self"在 Swift 中无法正常工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24291079/