swift - verificacion - referencias laborales ejemplos
¿Cómo puedo hacer una referencia de protocolo débil en Swift ''puro''(sin @objc)? (5)
weak
referencias weak
no parecen funcionar en Swift a menos que un protocol
se declare como @objc
, que no quiero en una aplicación Swift pura.
Este código da un error de compilación ( weak
no se puede aplicar a un tipo que no sea de clase MyClassDelegate
):
class MyClass {
weak var delegate: MyClassDelegate?
}
protocol MyClassDelegate {
}
Necesito prefijar el protocolo con @objc
, entonces funciona.
Pregunta: ¿Cuál es la manera ''pura'' y rápida de lograr un delegate
weak
?
Respuesta suplementaria
Siempre estaba confundido acerca de si los delegados debían ser débiles o no. Recientemente he aprendido más sobre los delegados y cuándo usar referencias débiles, así que permítame agregar algunos puntos adicionales aquí para el futuro de los espectadores.
El propósito de usar la palabra clave
weak
es evitar ciclos de referencia fuertes (ciclos de retención). Los ciclos de referencia fuertes ocurren cuando dos instancias de clase tienen referencias fuertes entre sí. Sus recuentos de referencias nunca van a cero, por lo que nunca se desasignan.Solo necesitas usar
weak
si el delegado es una clase. Las estructuras y enumeraciones de Swift son tipos de valor (sus valores se copian cuando se crea una nueva instancia), no tipos de referencia, por lo que no hacen ciclos de referencia fuertes.weak
referenciasweak
siempre son opcionales (de lo contrario, se utilizaríaunowned
) y siempre usevar
(nolet
) para que el opcional se pueda establecer ennil
cuando se desasigne.Una clase padre debería naturalmente tener una referencia fuerte a sus clases secundarias y, por lo tanto, no usar la palabra clave
weak
. Sin embargo, cuando un niño desea una referencia a su padre, debe convertirla en una referencia débil mediante el uso de la palabra claveweak
.Debería usarse
weak
cuando desea una referencia a una clase que no posee, no solo para un niño que hace referencia a su padre. Cuando dos clases no jerárquicas necesitan hacer referencia una a la otra, elija una para ser débil. El que elijas depende de la situación. Vea las respuestas a esta pregunta para más información sobre esto.Como regla general, los delegados deben marcarse como
weak
porque la mayoría de los delegados hacen referencia a clases que no son de su propiedad. Esto es definitivamente cierto cuando un niño está utilizando un delegado para comunicarse con un padre. Sin embargo, todavía hay algunas situaciones en las que un delegado puede y debe usar una referencia sólida.Los protocolos se pueden utilizar tanto para los tipos de referencia (clases) como para los tipos de valor (estructuras, enumeraciones). Por lo tanto, en el caso probable de que necesite debilitar a un delegado, debe agregar la palabra clave de
class
al protocolo para que sepa que solo debe usarse con tipos de referencia.protocol MyClassDelegate: class { // ... } class SomeClass { weak var delegate: MyClassDelegate? }
Estudio adicional
Leer los siguientes artículos es lo que me ayudó a entender esto mucho mejor. También discuten temas relacionados como la palabra clave unowned
y los ciclos de referencia fuertes que ocurren con los cierres.
- Documentación Swift: Conteo automático de referencias
- "Débil, fuerte, sin dueño, ¡oh Dios mío!" - Una guía de referencias en Swift
- Fuerte, débil y sin dueño - Clasificando ARC y Swift
Relacionado
- Cómo hacer delegados en Swift
- iOS: Cómo hacer delegados débiles en Swift
- Delegación rápida: cuándo usar el puntero débil en el delegado
Apple usa "NSObjectProtocol" en lugar de "class".
public protocol UIScrollViewDelegate : NSObjectProtocol {
...
}
Esto también funciona para mí y eliminó los errores que estaba viendo al intentar implementar mi propio patrón de delegado.
Necesitas declarar el tipo del protocolo como class
.
protocol ProtocolNameDelegate: class {
// Protocol stuff goes here
}
class SomeClass {
weak var delegate: ProtocolNameDelegate?
}
Mi entendimiento es que al usar la class
, usted garantiza que este protocolo se usará solo en las clases y no en otras cosas como enumeraciones o estructuras.
AnyObject
es la forma oficial de usar una referencia débil en Swift.
class MyClass {
weak var delegate: MyClassDelegate?
}
protocol MyClassDelegate: AnyObject {
}
De Apple:
Para evitar ciclos de referencia fuertes, los delegados deben ser declarados como referencias débiles. Para obtener más información sobre referencias débiles, consulte Ciclos de referencia fuertes entre instancias de clase. Marcar el protocolo como solo de clase más adelante le permitirá declarar que el delegado debe usar una referencia débil. Marque un protocolo como solo de clase al heredar de AnyObject , como se describe en Protocolos de solo clase.
Actualización: Parece que el manual se ha actualizado y el ejemplo al que me refería se ha eliminado. Ver la edición de la respuesta de @ flainez arriba.
Original: utilizar @objc es la forma correcta de hacerlo, incluso si no está interoperando con Obj-C. Asegura que su protocolo se aplique a una clase y no a una enumeración o estructura. Consulte "Comprobación de la conformidad del protocolo" en el manual.