¿Es necesario utilizar autoreleasepool en un programa Swift?
En la página 17 de esta presentación de la WWDC14 , dice
¿Trabajando con Objective-C? Todavía tengo que administrar los grupos de liberación automática
autoreleasepool { /* código */ }
¿Qué significa eso? ¿Significa que si mi código base no tiene archivos Objective-C, autoreleasepool {}
es innecesario?
En una respuesta a una pregunta relacionada , hay un ejemplo que autoreleasepool
puede resultar útil:
- (void)useALoadOfNumbers {
for (int j = 0; j < 10000; ++j) {
@autoreleasepool {
for (int i = 0; i < 10000; ++i) {
NSNumber *number = [NSNumber numberWithInt:(i+j)];
NSLog(@"number = %p", number);
}
}
}
}
Si el código anterior se traduce a Swift y autoreleasepool
se elimina, ¿Swift será lo suficientemente inteligente como para saber que la number
variable debe publicarse después de la primera }
(como lo hacen otros idiomas)?
El autoreleasepool
patrón se usa en Swift al devolver autorelease
objetos (creados por su código Objective-C o usando clases Cocoa). El autorelease
patrón en Swift funciona de manera muy similar a como lo hace en Objective-C. Por ejemplo, considere esta interpretación Swift de su método (creación de instancias NSImage
/ UIImage
objetos):
func useManyImages() {
let filename = pathForResourceInBundle
for _ in 0 ..< 5 {
autoreleasepool {
for _ in 0 ..< 1000 {
let image = NSImage(contentsOfFile: filename)
}
}
}
}
Si ejecuta esto en Instrumentos, verá un gráfico de asignaciones con 5
pequeñas colinas (debido al bucle for externo), como el siguiente:
Pero si lo hace sin el grupo de liberación automática, verá que el uso máximo de memoria es mayor:
Le autoreleasepool
permite administrar explícitamente cuándo se desasignan objetos de liberación automática en Swift, tal como lo hizo en Objective-C.
Nota: Cuando se trata de objetos nativos de Swift, generalmente no recibirá objetos de liberación automática. Es por eso que la presentación mencionó la advertencia de que sólo se necesita esto cuando "se trabaja con Objective-C", aunque desearía que Apple fuera más claro en este punto. Pero si se trata de objetos Objective-C (incluidas las clases Cocoa), pueden ser objetos de liberación automática, en cuyo caso esta interpretación Swift del @autoreleasepool
patrón Objective-C sigue siendo útil.
Si lo usaría en el código Objective-C equivalente, entonces lo usaría en Swift.
¿Swift será lo suficientemente inteligente como para saber que la variable numérica debe liberarse después del primer }
Sólo si Objective-C lo hace. Ambos operan según las reglas de administración de memoria de Cocoa.
Por supuesto, ARC sabe que eso number
sale del alcance al final de esa iteración del ciclo y, si lo retuvo, lo liberará allí. Sin embargo, eso no le indica si el objeto se lanzó automáticamente, porque -[NSNumber numberWithInt:]
puede haber devuelto o no una instancia de liberación automática. No hay manera de que puedas saberlo porque no tienes acceso a la fuente de -[NSNumber numberWithInt:]
.