什么时候我应该在关闭时使用捕获列表,何时使用弱与无主?

时间:2016-09-21 17:47:35

标签: ios swift

我正在阅读一本书,一个在viewcontroller中的方法:

func addNewWord() {
    // create our alert controller
    let ac = UIAlertController(title: "Add new word", message: nil, preferredStyle: .alert)
    // add two text fields, one for English and one for French
    ac.addTextField { textField in
        textField.placeholder = "English"
    }
    // ac.addTextField { (textField) in // also works.
    ac.addTextField { (textField: UITextField) in
        textField.placeholder = "French"
    }
    // create an "Add Word" button that submits the user's input
    let submitAction = UIAlertAction(title: "Add Word", style: .default) {
        [unowned self, ac] (action: UIAlertAction!) in
        // pull out the English and French words, or an empty string if there was a problem
        let firstWord = ac.textFields?[0].text ?? ""
        let secondWord = ac.textFields?[1].text ?? ""
        // submit the English and French word to the insertFlashcard() method
        self.insertFlashcard(first: firstWord, second: secondWord)
    }
    // add the submit action, plus a cancel button
    ac.addAction(submitAction)
    ac.addAction(UIAlertAction(title: "Cancel", style: .cancel))
    // present the alert controller to the user
    present(ac, animated: true)
}

我不明白为什么ac不需要标记unowned

何时是标记unownedweak的最佳时间?

感谢。

2 个答案:

答案 0 :(得分:2)

在大多数情况下,self是视图控制器或其他一些半持久对象。视图控制器在内存方面相当昂贵,因为它们管理了多少状态,包括视图层次结构。当视图控制器从App的导航流程中解除时,其资源确实需要被释放。所以设计模式总是要注意self,所以要避免过多引用VC。例如,如果关闭持续很长时间,但VC被解除导航,VC及其相关资源无用地扼杀了内存:内存泄漏。

相比之下,函数 的局部变量相对于包含的闭包具有更长的寿命 - 一旦包含函数退出,它们的初始引用计数就会保证递减。因此,仅关闭可以管理对它的引用,而不关心其应​​用程序范围的生命周期。

owned vs. weak实际上是一个不同的问题。这取决于你的应用程序设计 - 没有公式的答案。 unownedweak一样,增加闭包中捕获对象的保留计数。但是,这样就有可能捕获的对象以保留计数0结束,并且在关闭运行之前将被释放,从而有可能发生崩溃。因此,您需要确定,如果您说unowned其他 总是承担所有权责任。相反,将self声明为weak会将对象声明为volatile,并强制您检查(if let ...)对象是否已取消分配。

另外,我没有彻底检查相关链接,但我确信我重复了之前所说的很多内容。首先阅读高度赞成的帖子。

Shall we always use [unowned self] inside closure in Swift

optional closure property in Swift

编辑,真正的问题

你的书的代码毫无意义,因为手册特别说:

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html

  

这种区别[将变量完全从捕获列表中删除,   与包括它,但没有弱/无名指定]不是   捕获变量的类型具有引用语义时可见。对于   例如,下面的代码中有两个名为x的东西,一个变量   外部范围和内部范围中的常量,但它们都引用   由于引用语义而导致同一个对象。

换句话说,因为ac是一个引用类型对象,所以在捕获列表中包含它“裸”不会做任何事情。

我认为这本书有误,应该说[unowned self, unowned ac]

我的理由是:UIAlertController ac - >强烈引用submitAction(通过addAction) - >强烈提及匿名关闭 - >强烈提及ac。除非其中一个仅为此目的在内部声明为weak,否则unowned ac是必要的。太糟糕了一些是封闭源,我们无法确定。文档并不具体,因此我们必须假设这些文档都存储在库代码中。

答案 1 :(得分:1)

您的文字字段会立即被调用,不会引用自我或您的UIAlertController

稍后会调用操作块(当用户单击按钮时),因此需要存储对selfac的引用。通过存储此引用,您可以引入Circular References,这可能导致内存泄漏。基本上,如果您在操作块中使用对ac的强引用,则该块指向UIAlertControllerUIAlertController指向该块,并且没有任何内容被释放。