Andrew respondió a su pregunta principal de que, sí, su grupo de autoresas se agotará en cada ciclo del ciclo de ejecución principal. Entonces, cualquier objeto de autora de ejecución creado en viewDidLoad
Puede drenarse de inmediato cuando vuelva a ceder al bucle de ejecución principal. Ciertamente no serán retenidos "hasta la terminación de la aplicación".
Pero debemos tener cuidado: está claramente asumiendo que estos objetos se están agregando a un grupo de autoresas. Algunas advertencias a esta suposición:
En el pasado (y aún requerido para la interoperabilidad de ARC-MRC), al devolver objetos de los métodos cuyos nombres no comenzaron con alloc
, new
, copy
, o mutableCopy
, esos objetos se activarían los objetos de autorrealización, desaconsejados solo cuando se drenó el grupo de autoresas (es decir, cuando cedió al ciclo de ejecución).
Pero ARC se ha vuelto más inteligente sobre minimizar la necesidad de grupos de autoraselase (ver http://rentzsch.tumblr.com/post/75082194868/arcs-stast-eutorelease, que discute callerAcceptsFastAutorelease
, ahora llamado callerAcceptsOptimizedReturn
invocado por prepareOptimizedReturn
), por lo que a menudo no verás esto autorelease
comportamiento. Por lo tanto, si tanto la biblioteca como la persona que llama usa ARC, los objetos no pueden colocarse en el grupo de autorlease, sino que ARC los liberará inteligentemente de inmediato si no son necesarios.
Con los proyectos de ARC contemporáneos, las piscinas de autorhease generalmente no son necesarias. Pero ciertos casos especiales, uno aún puede beneficiarse del uso de grupos de autoresas. Cumpliré uno de esos casos a continuación.
Considere el siguiente código:
#import "ViewController.h"
#import <sys/kdebug_signpost.h>
typedef enum : NSUInteger {
InnerLoop = 1,
MainLoop = 2
} MySignPostCodes;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"png"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
kdebug_signpost_start(MainLoop, 0, 0, 0, 1);
for (int j = 0; j < 500; i++) {
NSData *data = [NSData dataWithContentsOfURL:fileURL];
UIImage *image = [[UIImage alloc] initWithData:data];
NSLog(@"%p", NSStringFromCGSize(image.size)); // so it's not optimized out
[NSThread sleepForTimeInterval:0.01];
}
kdebug_signpost_end(MainLoop, 0, 0, 0, 1);
});
}
@end
El siguiente código agregará 500,000 objetos al grupo de Autorelease, que solo se drenará cuando vuelva al ciclo de ejecución:
En este caso, puede usar una piscina de autoresas para minimizar la marca de agua alta:
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"png"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
kdebug_signpost_start(MainLoop, 0, 0, 0, 1);
for (int j = 0; j < 5; j++) {
@autoreleasepool {
kdebug_signpost_start(InnerLoop, 0, 0, 0, 2);
for (long i = 0; i < 100; i++) {
NSData *data = [NSData dataWithContentsOfURL:fileURL];
UIImage *image = [[UIImage alloc] initWithData:data];
NSLog(@"%p", NSStringFromCGSize(image.size)); // so it's not optimized out
[NSThread sleepForTimeInterval:0.01];
}
kdebug_signpost_end(InnerLoop, 0, 0, 0, 2);
}
}
kdebug_signpost_end(MainLoop, 0, 0, 0, 1);
});
}
@end
En pocas palabras, con ARC, no siempre es obvio cuando usó un objeto de autorazones y cuando lo libera explícitamente cuando la variable cae fuera del alcance. Siempre puede confirmar esto examinando el comportamiento en los instrumentos.
Como aparte, sería cauteloso al sacar demasiadas conclusiones generales de gestión de la memoria al usar el NSString
Clase, ya que ha sido altamente optimizado y no siempre se ajusta a las prácticas de gestión de memoria estándar.