ios - significado - que es el yo pdf
Cómo manejar correctamente el yo débil en Swift Blocks con argumentos (8)
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 declaración if
, la aplicación falla. ¿Alguna idea sobre cómo debería funcionar esto con [unowned 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
}()
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.
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 sintaxis opcional.
[unowned self]
funciona bien aquí porque la célula nunca será nula. De lo contrario, puede usar [weak 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 :
Nota: utilicé el término cierre en lugar de bloque, que es el término más nuevo de Swift:
Diferencia entre bloque (objetivo C) y cierre (Swift) en ios
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 bloqueo. (Es solo una suposición).
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 declaración 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) }