Objective-C Language
Minneshantering
Sök…
Automatisk referensräkning
Med automatisk referensräkning (ARC), kompilatorn insatserna retain
, release
och autorelease
uttalanden där de behövs, så att du inte behöver skriva dem själv. Den skriver också dealloc
metoder för dig.
Exempelprogrammet från Manual Memory Management ser ut så här med ARC:
@interface MyObject : NSObject {
NSString *_property;
}
@end
@implementation MyObject
@synthesize property = _property;
- (id)initWithProperty:(NSString *)property {
if (self = [super init]) {
_property = property;
}
return self;
}
- (NSString *)property {
return property;
}
- (void)setProperty:(NSString *)property {
_property = property;
}
@end
int main() {
MyObject *obj = [[MyObject alloc] init];
NSString *value = [[NSString alloc] initWithString:@"value"];
[obj setProperty:value];
[obj setProperty:@"value"];
}
Du kan fortfarande åsidosätta dealloc-metoden för att rensa upp resurser som inte hanteras av ARC. Till skillnad från när man använder manuell minneshantering ringer du inte [super dealloc]
.
-(void)dealloc {
//clean up
}
Starka och svaga referenser
En svag referens ser ut som en av dessa:
@property (weak) NSString *property;
NSString *__weak variable;
Om du har en svag referens till ett objekt, sedan under huven:
- Du behåller det inte.
- När den delas om kommer varje hänvisning till den automatiskt att ställas in på
nil
Objektreferenser är alltid starka som standard. Men du kan uttryckligen ange att de är starka:
@property (strong) NSString *property;
NSString *__strong variable;
En stark referens betyder att medan den referensen finns, behåller du objektet.
Manuell minnehantering
Detta är ett exempel på ett program skrivet med manuell minneshantering. Du borde verkligen inte skriva din kod så här, såvida du av någon anledning inte kan använda ARC (som om du behöver stödja 32-bitars). Exemplet undviker @property
notering för att illustrera hur du brukade skriva böcker och setare.
@interface MyObject : NSObject {
NSString *_property;
}
@end
@implementation MyObject
@synthesize property = _property;
- (id)initWithProperty:(NSString *)property {
if (self = [super init]) {
// Grab a reference to property to make sure it doesn't go away.
// The reference is released in dealloc.
_property = [property retain];
}
return self;
}
- (NSString *)property {
return [[property retain] autorelease];
}
- (void)setProperty:(NSString *)property {
// Retain, then release. So setting it to the same value won't lose the reference.
[property retain];
[_property release];
_property = property;
}
- (void)dealloc {
[_property release];
[super dealloc]; // Don't forget!
}
@end
int main() {
// create object
// obj is a reference that we need to release
MyObject *obj = [[MyObject alloc] init];
// We have to release value because we created it.
NSString *value = [[NSString alloc] initWithString:@"value"];
[obj setProperty:value];
[value release];
// However, string constants never need to be released.
[obj setProperty:@"value"];
[obj release];
}
Regler för minneshantering när man använder manuell referensräkning.
Dessa regler gäller endast om du använder manuell referensräkning!
Du äger alla objekt du skapar
Genom att anropa en metod vars namn börjar med
alloc
,new
,copy
ellermutableCopy
. Till exempel:NSObject *object1 = [[NSObject alloc] init]; NSObject *object2 = [NSObject new]; NSObject *object3 = [object2 copy];
Det betyder att du är ansvarig för att släppa dessa föremål när du är klar med dem.
Du kan ta ägande av ett objekt med behåll
För att ta ägande för ett objekt kallar du behållningsmetoden.
Till exempel:
NSObject *object = [NSObject new]; // object already has a retain count of 1 [object retain]; // retain count is now 2
Detta är bara meningsfullt i vissa sällsynta situationer.
Till exempel när du implementerar en accessor eller en init-metod för att ta ägande:
- (void)setStringValue:(NSString *)stringValue { [_privateStringValue release]; // Release the old value, you no longer need it [stringValue retain]; // You make sure that this object does not get deallocated outside of your scope. _privateStringValue = stringValue; }
När du inte längre behöver det måste du avstå från ägande av ett objekt du äger
NSObject* object = [NSObject new]; // The retain count is now 1 [object performAction1]; // Now we are done with the object [object release]; // Release the object
Du får inte avstå från ägande av ett objekt du inte äger
Det betyder att när du inte tog ägande av ett objekt släpper du inte det.
Autoreleasepool
Autoreleasepoolen är ett kodblock som släpper alla objekt i blocket som fick ett autoreleasmeddelande.
Exempel:
@autoreleasepool { NSString* string = [NSString stringWithString:@"We don't own this object"]; }
Vi har skapat en sträng utan att ta ägande.
NSString
metodenstringWithString:
måste se till att strängen är korrekt omplacerad efter att den inte längre behövs. Innan metoden återgår anropar den nyligen skapade strängen autoreleasmetoden så att den inte behöver ta äganderätt till strängen.Så implementeras
stringWithString:
:+ (NSString *)stringWithString:(NSString *)string { NSString *createdString = [[NSString alloc] initWithString:string]; [createdString autorelease]; return createdString; }
Det är nödvändigt att använda autoreleasepool-block eftersom du ibland har objekt som du inte äger (de fjärde reglerna gäller inte alltid).
Automatisk referensräkning tar automatiskt hand om reglerna så att du inte behöver göra det.