weak
Las referencias no parecen funcionar en Swift a menos que protocol
se declare como @objc
, lo que no quiero en una aplicación Swift pura.
Este código da un error de compilación ( weak
no se puede aplicar al tipo que no sea de clase MyClassDelegate
):
class MyClass {
weak var delegate: MyClassDelegate?
}
protocol MyClassDelegate {
}
Necesito prefijar el protocolo con @objc
, luego funciona.
Pregunta: ¿Cuál es la forma 'pura' rápida de lograr a weak
delegate
?
Respuestas:
Debe declarar el tipo de protocolo como
AnyObject
.Usando
AnyObject
usted dice que solo las clases pueden cumplir con este protocolo, mientras que las estructuras o enumeraciones no pueden.fuente
protocol ProtocolNameDelegate: AnyObject
, pero no importa.AnyObject
yaclass
que quedará en desuso en algún momento.Respuesta suplementaria
Siempre estaba confundido acerca de si los delegados deberían ser débiles o no. Recientemente, he aprendido más sobre los delegados y cuándo usar referencias débiles, así que permítanme agregar algunos puntos adicionales aquí por el bien de los futuros espectadores.
El propósito de usar la
weak
palabra clave es evitar ciclos de referencia fuertes (retener ciclos). Los ciclos de referencia fuertes ocurren cuando dos instancias de clase tienen referencias fuertes entre sí. Sus recuentos de referencia nunca llegan a cero, por lo que nunca se desasignan.Solo necesita usar
weak
si el delegado es una clase. Las estructuras y enumeraciones rápidas 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
las referencias son siempre opcionales (de lo contrario lo usaríaunowned
) y siempre usanvar
(nolet
) para que se pueda establecer lo opcionalnil
cuando se desasigna.Una clase principal debería tener una referencia fuerte a sus clases secundarias y, por lo tanto, no usar la
weak
palabra clave. Sin embargo, cuando un niño quiere una referencia a su padre, debe hacer una referencia débil al usar laweak
palabra clave.weak
debe usarse cuando desea una referencia a una clase que no es de su propiedad, no solo para un niño que hace referencia a su padre. Cuando dos clases no jerárquicas necesitan referenciarse entre sí, elija una para ser débil. El que elijas depende de la situación. Consulte las respuestas a esta pregunta para obtener más información al respecto.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á usando un delegado para comunicarse con un padre. Usar una referencia débil para el delegado es lo que recomienda la documentación . (Pero mira esto también).Los protocolos se pueden usar tanto para tipos de referencia (clases) como para tipos de valores (estructuras, enumeraciones). Entonces, en el caso probable de que necesite debilitar a un delegado, debe convertirlo en un protocolo de solo objeto. La forma de hacerlo es agregar
AnyObject
a la lista de herencia del protocolo. (En el pasado hiciste esto usando laclass
palabra clave, peroAnyObject
ahora se prefiere ).Estudio adicional
Leer los siguientes artículos es lo que me ayudó a entender esto mucho mejor. También discuten temas relacionados como la
unowned
palabra clave y los ciclos de referencia fuertes que ocurren con los cierres.Relacionado
fuente
AnyObject
es la forma oficial de usar una referencia débil en Swift.De Apple:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID276
fuente
class
en desuso en Swift 4.1?Actualización: Parece que el manual se ha actualizado y el ejemplo al que me refería se ha eliminado. Vea la edición de la respuesta de @ flainez arriba.
Original: usar @objc es la forma correcta de hacerlo, incluso si no interopera con Obj-C. Asegura que su protocolo se aplique a una clase y no a una enumeración o estructura. Consulte "Comprobación de conformidad de protocolo" en el manual.
fuente
El protocolo debe ser subclase de AnyObject, clase
ejemplo dado a continuación
fuente
Apple usa "NSObjectProtocol" en lugar de "clase".
Esto también funciona para mí y eliminó los errores que estaba viendo al intentar implementar mi propio patrón de delegado.
fuente