Cómo manejar correctamente el yo débil en Swift Blocks con argumentos

En mi TextViewTableViewCell , tengo una variable para hacer un seguimiento de un bloque y un método de configuración donde el bloque se pasa y se asigna.
Aquí está mi clase 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) } } } 

Cuando uso el método de configuración en mi método cellForRowAtIndexPath , ¿cómo uso correctamente el Yo débil en el bloque que paso?
Esto es lo que tengo sin el yo débil:

 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 

ACTUALIZACIÓN : obtuve lo siguiente para trabajar usando [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 

Cuando hago [unowned self] lugar de [weak self] y saco la statement if , la aplicación falla. ¿Alguna idea sobre cómo debería funcionar esto con [unowned self] ?

Si el yo puede ser nulo en el uso de cierre [yo débil] .

Si el yo nunca será nulo en el uso de cierre [yo sin dueño] .

Si está fallando cuando usas [self sin dueño] , supongo que ese self es nulo en algún momento de ese cierre, por lo que en su lugar debiste ir con [weak self] .

Me gustó mucho toda la sección del manual sobre el uso de cierres fuertes , débiles y sin dueño :

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

Nota: utilicé el término cierre en lugar de bloque, que es el término más nuevo de Swift:

Diferencia entre bloque (objective C) y cierre (Swift) en ios

Ponga [unowned self] antes (text: String)... en su cierre. Esto se llama una lista de captura y coloca instrucciones de propiedad en los símbolos capturados en el cierre.

Use la lista de captura

Definiendo una lista de captura

Cada elemento en una lista de captura es un emparejamiento de la palabra clave débil o sin propietario con una referencia a una instancia de clase (como self) o una variable inicializada con algún valor (como delegate = self.delegate!). Estas parejas se escriben dentro de un par de llaves cuadradas, separadas por comas.

Coloque la lista de captura antes de la lista de parámetros de un cierre y devuelva el tipo si se proporcionan:

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

Si un cierre no especifica una lista de parámetros o un tipo de devolución porque se pueden inferir del contexto, coloque la lista de captura al comienzo del cierre, seguida de la palabra clave in:

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

explicaciones adicionales

EDITADO: Como @ tim-vermeulen ha comentado, Chris Lattner dijo el vie 22 de enero a las 19:51:29 CST 2016, este truco no debe usarse en sí mismo, así que no lo use. Verifique la información de cierres que no se escapan y la respuesta de la lista de captura de @gbk.

Para aquellos que usan [yo débil] en la lista de captura, nótese que el yo podría ser nulo, así que lo primero que hago es verificarlo con una statement de guardia

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

Si te estás preguntando qué son las comillas alrededor de ti self es un truco para usarlo dentro del cierre sin necesidad de cambiar el nombre a esto , weakSelf o lo que sea.

PD: Como estoy obteniendo algunos votos, me gustaría recomendar la lectura sobre cierres que no escapan . TL; DR La mayoría de los métodos llaman al final el cierre pasado por argumento, si este es el caso, puede usar @noescape en el argumento de cierre y puede referirse a sí mismo implícitamente dentro del cierre.

EDITAR: Se eliminó el truco del “yo”

Como no se recomienda la solución de LightMan , generalmente hago:

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

O:

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

Por lo general, no es necesario especificar el tipo de parámetro si se deduce.

Puede omitir el parámetro por completo si no lo hay o si se refiere a él como $0 en el cierre:

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

Solo por completitud; si pasas el cierre a una función y el parámetro no es @escaping , no necesitas un weak self :

 [1,2,3,4,5].forEach { self.someCall($0) } 

Puede usar [self débil] o [self no propietario] en la lista de captura antes de sus parámetros del bloque. La lista de captura es syntax opcional.

[unowned self] funciona bien aquí porque la célula nunca será nula. De lo contrario, puede usar [weak self]

Usa el nombre strongSelf, es más explícito IMO

 _ = { [weak self] value in guard let strongSelf = self else { return } print(strongSelf) //👈 will never be nil }() 

Si se está cayendo de lo que probablemente necesita [yo débil]

Mi suposición es que el bloque que estás creando de alguna manera todavía está conectado.

Cree un prepareForReuse e intente borrar el bloque onTextViewEditClosure dentro de eso.

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

Vea si eso previene el locking. (Es solo una suposición).