Andrew ha risposto alla tua domanda principale che, sì, il tuo pool di autolesioni sarà svuotato su ogni ciclo del ciclo di corsa principale. Quindi qualsiasi oggetto di autolelease creati in viewDidLoad
Può essere pronta a drenare quando si cede al ciclo di corsa principale. Certamente non saranno mantenuti "fino alla risoluzione dell'applicazione".
Ma dovremmo stare attenti: stai chiaramente supponendo che questi oggetti vengano aggiunti a un pool di autolesi. Alcuni avvertimenti a questo presupposto:
In passato (e ancora richiesto per l'interoperabilità ARC-MRC), quando si restituiscono oggetti da metodi i cui nomi non iniziavano con alloc
, new
, copy
, o mutableCopy
, quegli oggetti avrebbero autorelease oggetti, si sono accordati solo quando il pool di autolesso è stato drenato (cioè quando si è cessati al ciclo di corsa).
Ma ARC è diventato più intelligente per ridurre al minimo la necessità di pool di autolesi (vedi http://rentzsch.tumblr.com/post/75082194868/arcs-fast-autolelease, che discute callerAcceptsFastAutorelease
, ora chiamato callerAcceptsOptimizedReturn
invocato da prepareOptimizedReturn
), quindi spesso non vedrai questo autorelease
comportamento. Quindi, se sia la libreria che il chiamante utilizzano l'arco, gli oggetti potrebbero non essere inseriti nel pool di autolesi, ma piuttosto l'arco li rilascerà abilmente immediatamente se non sono necessari.
Con i progetti ARC contemporanei, i pool di autolesi non sono generalmente necessari. Ma alcuni casi speciali, si possono comunque beneficiare dell'utilizzo di pool di autolesi. Descriverò uno di quei casi di seguito.
Considera il seguente codice:
#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
Il seguente codice aggiungerà 500.000 oggetti al pool di autolelease, che verrà drenato solo quando cedo al ciclo di corsa:
In questo caso, è possibile utilizzare una piscina per autolesi per ridurre al minimo il marchio di acqua elevata:
@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
In conclusione, con l'arco, non è sempre ovvio quando ha usato un oggetto di autoleasico e quando lo rilascia esplicitamente quando la variabile cade dall'ambito. Puoi sempre confermarlo esaminando il comportamento negli strumenti.
A parte questo, sarei diffidente nel trarre troppe conclusioni di gestione della memoria generale quando si usa il NSString
Classe, in quanto è stata altamente ottimizzata e non è sempre conforme alle pratiche di gestione della memoria standard.