Swift Language
Gestión de la memoria
Buscar..
Introducción
Unmanaged
] [1]. [1]: https://developer.apple.com/reference/swift/unmanaged
Observaciones
Cuándo usar la palabra clave débil:
La palabra claveweak
debe usarse, si un objeto referenciado puede ser desasignado durante la vida útil del objeto que contiene la referencia. Cuándo usar la palabra clave sin dueño:
Se debe usar la palabra claveunowned
propietario, si no se espera que un objeto referenciado se desasigne durante la vida útil del objeto que contiene la referencia. Escollos
Un error frecuente es olvidarse de crear referencias a objetos, que se requieren para vivir después de que finaliza una función, como administradores de ubicación, administradores de movimiento, etc.Ejemplo:
class A : CLLocationManagerDelegate
{
init()
{
let locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.startLocationUpdates()
}
}
Este ejemplo no funcionará correctamente, ya que el administrador de ubicación se desasigna una vez que el inicializador regresa. La solución adecuada es crear una referencia fuerte como una variable de instancia:
class A : CLLocationManagerDelegate
{
let locationManager:CLLocationManager
init()
{
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.startLocationUpdates()
}
}
Ciclos de referencia y referencias débiles
Un ciclo de referencia (o ciclo de retención ) se llama así porque indica un ciclo en el gráfico de objetos :
Cada flecha indica un objeto que retiene otro (una referencia fuerte). A menos que el ciclo se rompa, la memoria de estos objetos nunca se liberará .
Se crea un ciclo de retención cuando dos instancias de clases se hacen referencia:
class A { var b: B? = nil }
class B { var a: A? = nil }
let a = A()
let b = B()
a.b = b // a retains b
b.a = a // b retains a -- a reference cycle
Ambas instancias vivirán hasta que el programa termine. Este es un ciclo de retención.
Referencias débiles
Para evitar los ciclos de retención, use la palabra clave weak
o unowned
al crear referencias para romper los ciclos de retención.
class B { weak var a: A? = nil }
Las referencias débiles o sin propiedad no aumentarán el recuento de referencias de una instancia. Estas referencias no contribuyen a retener los ciclos. La referencia débil se vuelve nil
cuando el objeto al que hace referencia se desasigna.
a.b = b // a retains b
b.a = a // b holds a weak reference to a -- not a reference cycle
Cuando trabaje con cierres, también puede usar weak
y unowned
en las listas de captura .
Gestión de memoria manual
Al interactuar con las API de C, es posible que desee retroceder el contador de referencia de Swift. Al hacerlo se logra con objetos no gestionados.
Si necesita suministrar un puntero de tipo punted a una función C, use el método de toOpaque
de la estructura no Unmanaged
para obtener un puntero sin fromOpaque
y de fromOpaque
para recuperar la instancia original:
setupDisplayLink() {
let pointerToSelf: UnsafeRawPointer = Unmanaged.passUnretained(self).toOpaque()
CVDisplayLinkSetOutputCallback(self.displayLink, self.redraw, pointerToSelf)
}
func redraw(pointerToSelf: UnsafeRawPointer, /* args omitted */) {
let recoveredSelf = Unmanaged<Self>.fromOpaque(pointerToSelf).takeUnretainedValue()
recoveredSelf.doRedraw()
}
Tenga en cuenta que, si utiliza passUnretained
y sus homólogos, es necesario tomar todas las precauciones como con las referencias unowned
.
Para interactuar con las API heredadas de Objective-C, uno podría querer afectar manualmente el conteo de referencias de un determinado objeto. Para eso Unmanaged
tiene métodos respectivos de retain
y release
. No obstante, es más deseable usar passRetained
y takeRetainedValue
, que realizan la retención antes de devolver el resultado:
func preferredFilenameExtension(for uti: String) -> String! {
let result = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension)
guard result != nil else { return nil }
return result!.takeRetainedValue() as String
}
Estas soluciones siempre deben ser el último recurso, y las API nativas de idioma siempre deben ser preferidas.