En mi TextViewTableViewCell
, tengo una variable para realizar un seguimiento de un bloque y un método de configuración donde el bloque se pasa y se asigna.
Aquí está mi TextViewTableViewCell
clase:
//
// 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 cellForRowAtIndexPath
método, ¿cómo utilizo 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 : Tengo 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 lo hago en [unowned self]
lugar de [weak self]
y saco la if
declaración, la aplicación se bloquea. ¿Alguna idea sobre cómo debería funcionar esto [unowned self]
?
ios
swift
retain-cycle
NatashaTheRobot
fuente
fuente
Respuestas:
Si el self puede ser nulo en el cierre, use [self débil] .
Si el self nunca será nulo en el cierre, use [self sin dueño] .
Si se cuelga cuando usas [yo sin propiedad] , supongo que ese yo es nulo en algún momento de ese cierre, por lo que tuviste que ir con [yo débil] .
Realmente me gustó toda la sección del manual sobre el uso de cierres fuertes , débiles y sin propiedad:
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 Swift más nuevo:
Diferencia entre bloqueo (Objetivo C) y cierre (Swift) en ios
fuente
unowned
. No vale la pena correr el riesgo de hacer que su aplicación se bloquee.Poner
[unowned self]
antes(text: String)...
en su cierre. Esto se llama una lista de captura y coloca instrucciones de propiedad sobre los símbolos capturados en el cierre.fuente
** EDITADO para Swift 4.2:
Como comentó @Koen, swift 4.2 permite:
PD: Dado que tengo algunos votos positivos, me gustaría recomendar la lectura sobre cómo escapar de los cierres .
EDITADO: Como ha comentado @ tim-vermeulen, Chris Lattner dijo el viernes 22 de enero a las 19:51:29 CST 2016, este truco no debe usarse solo, así que no lo use. Verifique la información de los cierres que no escapan y la respuesta de la lista de captura de @gbk. **Para aquellos que usan [self débil] en la lista de captura, tenga en cuenta que self podría ser nulo, por lo que lo primero que hago es verificar eso con una declaración de guardia
Si se pregunta cuáles son las comillas,
self
es un truco profesional para usar uno mismo dentro del cierre sin necesidad de cambiar el nombre a este , débilSelf o lo que sea.fuente
self
(en backticks). Póngale otro nombre como nonOptionalSelf y estará bien.{ [weak self] in guard let self = self else { return }
se puede usar sin backticks, y en realidad es compatible: github.com/apple/swift-evolution/blob/master/proposals/…Usar lista de captura
explicaciones adicionales
fuente
EDITAR: referencia a una solución actualizada de LightMan
Ver la solución de LightMan . Hasta ahora estaba usando:
O:
Por lo general, no necesita especificar el tipo de parámetro si se infiere.
Puede omitir el parámetro por completo si no hay ninguno o si se refiere a él como
$0
en el cierre:Solo para completar; Si pasa el cierre a una función y el parámetro no lo es
@escaping
, no necesita unweak self
:fuente
A partir de swift 4.2 🔸 podemos hacer:
fuente
strongSelf
explica explícitamente el significado de las variables / efecto secundario, lo cual es bueno si el código es más extenso. Sin embargo, agradezco su opinión, no sabía que C ++ usaba tal fraseo.guard let self = self else { return }
para desenvolver[weak self]
: github.com/apple/swift-evolution/blob/master/proposals/…Swift 4.2
https://github.com/apple/swift-evolution/blob/master/proposals/0079-upgrade-self-from-weak-to-strong.md
fuente
Puede usar [yo débil] o [yo no propio] en la lista de captura antes de sus parámetros del bloque. La lista de captura es una sintaxis opcional.
[unowned self]
funciona bien aquí porque la celda nunca será nula. De lo contrario, puede usar[weak self]
fuente
Si se estrella de lo que probablemente necesite [yo débil]
Supongo que el bloque que está creando todavía está conectado de alguna manera.
Cree un prepareForReuse e intente borrar el bloque onTextViewEditClosure dentro de eso.
Vea si eso previene el choque. (Es solo una suposición).
fuente
Cierre y fuertes ciclos de referencia [Acerca de]
Como saben, el cierre de Swift puede capturar la instancia. Significa que puede usar
self
dentro de un cierre. Especialmenteescaping closure
[Acerca de] puede crear unstrong reference cycle
que. Por cierto, tienes que usar explícitamenteself
dentroescaping closure
.El cierre rápido tiene una
Capture List
función que le permite evitar tal situación y romper un ciclo de referencia porque no tiene una referencia fuerte a la instancia capturada. El elemento Lista de captura es un par deweak
/unowned
y una referencia a clase o variable.Por ejemplo
weak
- más preferible, úselo cuando sea posibleunowned
- Úselo cuando esté seguro de que la vida útil del propietario de la instancia es mayor que el cierrefuente