Tanto las referencias weak
como las unowned
referencias no crean una strong
retención en el objeto referido (es decir, no aumentan el conteo de retención para evitar que ARC desasigne el objeto referido).
¿Pero por qué dos palabras clave? Esta distinción tiene que ver con el hecho de que los Optional
tipos están integrados en el lenguaje Swift. En pocas palabras: los tipos opcionales ofrecen seguridad en la memoria (esto funciona muy bien con las reglas de construcción de Swift, que son estrictas para proporcionar este beneficio).
Una weak
referencia permite la posibilidad de que se convierta nil
(esto sucede automáticamente cuando el objeto referenciado se desasigna), por lo tanto, el tipo de su propiedad debe ser opcional, por lo que usted, como programador, está obligado a verificarlo antes de usarlo (básicamente el el compilador lo obliga, tanto como puede, a escribir código seguro).
Una unowned
referencia supone que nunca se convertirá nil
durante su vida útil. Se debe establecer una referencia no propia durante la inicialización; esto significa que la referencia se definirá como un tipo no opcional que se puede utilizar de forma segura sin controles. Si de alguna manera el objeto al que se hace referencia se desasigna, la aplicación se bloqueará cuando se use la referencia no propiedad.
De los documentos de Apple :
Utilice una referencia débil siempre que sea válida para que esa referencia sea nula en algún momento durante su vida útil. Por el contrario, use una referencia no propia cuando sepa que la referencia nunca será nula una vez que se haya establecido durante la inicialización.
En los documentos, hay algunos ejemplos que analizan los ciclos de retención y cómo romperlos. Todos estos ejemplos se extraen de los documentos .
Ejemplo de la weak
palabra clave:
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
}
class Apartment {
let number: Int
init(number: Int) { self.number = number }
weak var tenant: Person?
}
Y ahora, para algunas ilustraciones ASCII (deberías ir a ver los documentos , tienen diagramas bonitos):
Person ===(strong)==> Apartment
Person <==(weak)===== Apartment
El ejemplo Person
y Apartment
muestra una situación en la que dos propiedades, que pueden ser nulas, tienen el potencial de causar un ciclo de referencia fuerte. Este escenario se resuelve mejor con una referencia débil. Ambas entidades pueden existir sin tener una dependencia estricta de la otra.
Ejemplo de la unowned
palabra clave:
class Customer {
let name: String
var card: CreditCard?
init(name: String) { self.name = name }
}
class CreditCard {
let number: UInt64
unowned let customer: Customer
init(number: UInt64, customer: Customer) { self.number = number; self.customer = customer }
}
En este ejemplo, a Customer
puede o no tener a CreditCard
, pero a CreditCard
siempre estará asociado con a Customer
. Para representar esto, la Customer
clase tiene una card
propiedad opcional , pero la CreditCard
clase tiene una propiedad no opcional (y no propia) customer
.
Customer ===(strong)==> CreditCard
Customer <==(unowned)== CreditCard
El ejemplo Customer
y CreditCard
muestra una situación en la que una propiedad que puede ser nula y otra propiedad que no puede ser nula tiene el potencial de causar un ciclo de referencia fuerte. Este escenario se resuelve mejor con una referencia no propiedad.
Nota de Apple:
Las referencias débiles deben declararse como variables para indicar que su valor puede cambiar en tiempo de ejecución. Una referencia débil no puede declararse como una constante.
También hay un tercer escenario en el que ambas propiedades siempre deben tener un valor, y ninguna de ellas debe ser nula una vez que se complete la inicialización.
Y también están los escenarios clásicos de ciclo de retención para evitar al trabajar con cierres.
Para esto, te animo a que visites los documentos de Apple o leas el libro .