如何正确处理有争议的快速障碍弱势群体

在我的TextViewTableViewCell ,我有一个variables来跟踪一个块和一个configuration方法,在这个块被传入和分配。
这是我的TextViewTableViewCell类:

 // // TextViewTableViewCell.swift // import UIKit class TextViewTableViewCell: UITableViewCell, UITextViewDelegate { @IBOutlet var textView : UITextView var onTextViewEditClosure : ((text : String) -> Void)? func configure(#text: String?, onTextEdit : ((text : String) -> Void)) { onTextViewEditClosure = onTextEdit textView.delegate = self textView.text = text } // #pragma mark - Text View Delegate func textViewDidEndEditing(textView: UITextView!) { if onTextViewEditClosure { onTextViewEditClosure!(text: textView.text) } } } 

当我在我的cellForRowAtIndexPath方法中使用configure方法时,如何在我传入的块中正确使用weak self。
这就是我没有弱自我所拥有的东西:

 let myCell = tableView.dequeueReusableCellWithIdentifier(textViewCellIdenfitier) as TextViewTableViewCell myCell.configure(text: body, onTextEdit: {(text: String) in // THIS SELF NEEDS TO BE WEAK self.body = text }) cell = bodyCell 

更新 :我有以下工作使用[weak self]

 let myCell = tableView.dequeueReusableCellWithIdentifier(textViewCellIdenfitier) as TextViewTableViewCell myCell.configure(text: body, onTextEdit: {[weak self] (text: String) in if let strongSelf = self { strongSelf.body = text } }) cell = myCell 

当我做[unowned self]而不是[weak self]并取出if语句,应用程序崩溃。 任何想法如何与[unowned self]

如果自我可能在封闭使用[弱自我]

如果封闭使用[无主的自我], 自我永远不会成为零。

如果在使用[无主自我]的时候它会崩溃,那么我会猜想在这个闭包的某个点上自我是零,这就是为什么你必须用[weak self]来代替。

我真的很喜欢手册中关于使用强大弱势无主的closures的整个部分:

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

注:我使用了术语闭包而不是 ,这是更新的Swift术语:

ios中block(Objective C)和closure(Swift)之间的区别

[unowned self]放在(text: String)...之前。 这被称为捕获列表 ,并将所有权指令放置在闭包中捕获的符号上。

编辑:正如@ tim-vermeulen所说,克里斯·拉特纳在1月22日星期五19:51:29 CST 2016上说,这个招数不应该用在自己身上,所以请不要使用它。 从@gbk检查非转义closures信息和捕获列表答案。

对于那些在捕捉列表中使用[weak self]的人,请注意自己可能是零,所以我做的第一件事就是用guard语句

 guard let `self` = self else { return } self.doSomething() 

如果你想知道引号是在什么附近,那么self就是一个在封闭的情况下使用self而不需要改变名字, weakSelf或者其他东西的专业技巧。

PS:由于我有些赞成票,所以我想推荐阅读关于不可逃脱的封闭 。 TL; DR大多数方法在最后调用通过parameter passing的闭包,如果是这种情况,您可以在闭包参数中使用@noescape,并且可以在闭包中隐式引用自己。

使用捕获列表

定义一个捕获列表

捕获列表中的每个项目都是弱关键字或无主关键字与对类实例(如self)的引用或用某个值初始化的variables(如delegate = self.delegate!)的配对。 这些配对写在一对方括号内,用逗号隔开。

将捕获列表放在闭包的参数列表之前,如果提供了返回types:

 lazy var someClosure: (Int, String) -> String = { [unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in // closure body goes here } 

如果闭包没有指定参数列表或返回types,因为它们可以从上下文中推断出来,请将捕获列表放在闭包的开头,然后是in关键字:

 lazy var someClosure: Void -> String = { [unowned self, weak delegate = self.delegate!] in // closure body goes here } 

额外的解释

您可以使用LightMan的解决scheme,或者在某些情况下,可以select调用一个方法:

 input.action = { [weak self] value in self?.someCall(value) // call is done if self isn't nil } 

为了完整性,我将扩展LightMan解决scheme:

 input.action = { [weak self] value in guard let `self` = self else { return } self.someCall(value) // self isn't nil } 

通常,如果推断,则不需要指定参数types。

或者,如果闭包没有参数,那就去掉它。 🙂

您可以在块的参数之前在捕获列表中使用[weak self]或[unowned self]。 捕获列表是可选的语法。

[unowned self]在这里工作很好,因为细胞永远不会是零。 否则,你可以使用[weak self]

如果你正在崩溃,你可能需要[弱自己]

我的猜测是,你正在创build的块还是以某种方式连接起来的。

创build一个prepareForReuse,并尝试清除内部的onTextViewEditClosure块。

 func prepareForResuse() { onTextViewEditClosure = nil textView.delegate = nil } 

看看是否可以防止崩溃。 (这只是一个猜测)。