我正在阅读一本书,一个在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
?
何时是标记unowned
或weak
的最佳时间?
感谢。
答案 0 :(得分:2)
在大多数情况下,self
是视图控制器或其他一些半持久对象。视图控制器在内存方面相当昂贵,因为它们管理了多少状态,包括视图层次结构。当视图控制器从App的导航流程中解除时,其资源确实需要被释放。所以设计模式总是要注意self
,所以要避免过多引用VC。例如,如果关闭持续很长时间,但VC被解除导航,VC及其相关资源无用地扼杀了内存:内存泄漏。
相比之下,函数 的局部变量相对于包含的闭包具有更长的寿命 - 一旦包含函数退出,它们的初始引用计数就会保证递减。因此,仅关闭可以管理对它的引用,而不关心其应用程序范围的生命周期。
owned
vs. weak
实际上是一个不同的问题。这取决于你的应用程序设计 - 没有公式的答案。 unowned
与weak
一样,不增加闭包中捕获对象的保留计数。但是,这样就有可能捕获的对象以保留计数0结束,并且在关闭运行之前将被释放,从而有可能发生崩溃。因此,您需要确定,如果您说unowned
,其他 总是承担所有权责任。相反,将self
声明为weak
会将对象声明为volatile,并强制您检查(if let
...)对象是否已取消分配。
另外,我没有彻底检查相关链接,但我确信我重复了之前所说的很多内容。首先阅读高度赞成的帖子。
Shall we always use [unowned self] inside closure in Swift
optional closure property in Swift
编辑,真正的问题
你的书的代码毫无意义,因为手册特别说:
这种区别[将变量完全从捕获列表中删除, 与包括它,但没有弱/无名指定]不是 捕获变量的类型具有引用语义时可见。对于 例如,下面的代码中有两个名为x的东西,一个变量 外部范围和内部范围中的常量,但它们都引用 由于引用语义而导致同一个对象。
换句话说,因为ac
是一个引用类型对象,所以在捕获列表中包含它“裸”不会做任何事情。
我认为这本书有误,应该说[unowned self, unowned ac]
。
我的理由是:UIAlertController ac
- >强烈引用submitAction
(通过addAction
) - >强烈提及匿名关闭 - >强烈提及ac
。除非其中一个仅为此目的在内部声明为weak
,否则unowned ac
是必要的。太糟糕了一些是封闭源,我们无法确定。文档并不具体,因此我们必须假设这些文档都存储在库代码中。
答案 1 :(得分:1)
您的文字字段会立即被调用,不会引用自我或您的UIAlertController
。
稍后会调用操作块(当用户单击按钮时),因此需要存储对self
或ac
的引用。通过存储此引用,您可以引入Circular References,这可能导致内存泄漏。基本上,如果您在操作块中使用对ac
的强引用,则该块指向UIAlertController
,UIAlertController
指向该块,并且没有任何内容被释放。