09.06.2008
Autorelease Pool (ARP)
Mit dem Autorelease-Pool (ARP) lassen sich viele Probleme in Bezug auf die Speicherfreigabe lösen. Wird beispielsweise ein Objekt erzeugt und es ist nicht klar, wie lange es benötigt wird und wer es zu gegebenen Zeit wieder deallokiert, d.h. den Speicher freigibt, dann wird der ARP eingesetzt.
Die folgende Klasse Car repräsentiert ein Auto mit einer Farbe und einer Marke. Die Header-Datei sieht so aus:
#import <Cocoa/Cocoa.h> @interface Car : NSObject { NSString* brand; //Car brand NSString* color; //Car color } //Init - (Car*)initWithBrand:(NSString*)newBrand color:(NSString*)newColor; // getter and setter for brand - (NSString*)brand; - (void)setBrand:(NSString*)newBrand; // getter and setter for color - (NSString*)color; - (void)setColor:(NSString*)newColor; @end
Also nichts besonderes. Die Implementierung dazu sieht folgendermaßen aus:
#import "Car.h" @implementation Car - (NSString*)brand { return brand; } - (void)setBrand:(NSString*)newBrand { if(newBrand != brand) { [brand release]; brand = [newBrand retain]; } } - (NSString*)color { return color; } - (void)setColor:(NSString*)newColor { if(newColor != color) { [color release]; color = [newColor retain]; } } - (Car*)initWithBrand:(NSString*)newBrand color:(NSString*)newColor { self = [super init]; [self setBrand:newBrand]; [self setColor:newColor]; NSLog(@"initWithBrand Brand:%@ Color:%@", [self brand], [self color]); return self; } - (void) dealloc { NSLog(@"Dealloc Car"); [self setBrand:nil]; [self setColor:nil]; [super dealloc]; } @end
Damit zu sehen ist, wann die Initialisierung und die Deallokierung durchgeführt wird, habe ich ein paar Log-Ausgaben ergänzt.
Normalerweise würde der Programmcode folgendermaßen aussehen:
#import <Foundation/Foundation.h> #import "Car.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Car* car; car = [[Car alloc]initWithBrand:@"BMW" color:@"Black"]; [car release]; [pool release]; return 0; }
Der Speicher für Car wird allokiert und das Objekt wird initialisiert. Wenn es nicht mehr benötigt wird, dann wird es mit release wieder freigegeben.
Eine andere Variante ist im Folgenden zu sehen:
#import <Foundation/Foundation.h> #import "Car.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Car* car; car = [[[Car alloc]initWithBrand:@"BMW" color:@"Black"]autorelease]; NSLog(@"Show brand %@ and color %@", [car brand], [car color]); [pool release]; NSLog(@"End of processing..."); return 0; }
Hier wird ein autorelease an das Objekt geschickt. Wenn jetzt der pool freigebenen wird, dann wird auch car freigegeben.
Die Ausgabe zu dem Programm auf der Konsole sieht folgendermaßen aus:
2008-06-09 10:24:20.573 TestProject[49063:10b] initWithBrand Brand:BMW Color:Black 2008-06-09 10:24:20.587 TestProject[49063:10b] Show brand BMW and color Black 2008-06-09 10:24:20.592 TestProject[49063:10b] Dealloc Car 2008-06-09 10:24:20.597 TestProject[49063:10b] End of processing...
Es ist zu sehen, daß das Objekt deallokiert wird, sobald der Pool freigegeben wird.