closures - 为什么闭包中的 "unowned self"在 Swift 中无法正常工作?

标签 closures swift

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/

相关文章:

perl - 使用闭包作为迭代器

objective-c - 如何从闭包中强制捕获?

swift - 在 macOS 中使用 swift 实现文档拖拽到应用程序

javascript - 在 JavaScript 中更改映射中的值和闭包中的引用

javascript - 你能说这是 Javascript Closure 的一个正确的例子吗?我们需要考虑避免闭包的地方在哪里?

使用一个或两个参数进行闭包的常规方法

ios - 将数组转换为 SwiftyJSON

objective-c - 是否可以根据修改键更改 NSOpenPanel 的提示

ios - 根据 UITextView 的 contentSize 调整特定表格 View 单元格的大小

swift - 在数组中搜索作为搜索字符串前缀的最长字符串