Objective-C Language
Zarządzanie pamięcią
Szukaj…
Automatyczne zliczanie referencji
Dzięki automatycznemu zliczaniu referencji (ARC), kompilator wstawia instrukcje retain
, release
i automatycznego autorelease
tam, gdzie są potrzebne, więc nie musisz pisać ich sam. Pisze także metody dealloc
.
Przykładowy program z ręcznego zarządzania pamięcią wygląda tak z 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"];
}
Nadal możesz zastąpić metodę dealloc, aby wyczyścić zasoby nieobsługiwane przez ARC. W przeciwieństwie do ręcznego zarządzania pamięcią nie wywołujesz [super dealloc]
.
-(void)dealloc {
//clean up
}
Mocne i słabe referencje
Słabe odniesienie wygląda następująco:
@property (weak) NSString *property;
NSString *__weak variable;
Jeśli masz słabe odniesienie do obiektu, to pod maską:
- Nie zachowujesz tego.
- Kiedy zostanie zwolniony, każde odniesienie do niego zostanie automatycznie ustawione na
nil
Odwołania do obiektów są zawsze domyślnie silne. Ale możesz wyraźnie określić, że są silne:
@property (strong) NSString *property;
NSString *__strong variable;
Silne odniesienie oznacza, że dopóki takie odniesienie istnieje, zachowujesz obiekt.
Ręczne zarządzanie pamięcią
To jest przykład programu napisanego z ręcznym zarządzaniem pamięcią. Naprawdę nie powinieneś pisać takiego kodu, chyba że z jakiegoś powodu nie możesz użyć ARC (np. Jeśli potrzebujesz obsługi 32-bitowej). W tym przykładzie nie @property
notacji @property
aby zilustrować sposób pisania getterów i settererów.
@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];
}
Reguły zarządzania pamięcią podczas ręcznego zliczania referencji.
Te zasady obowiązują tylko w przypadku ręcznego liczenia referencji!
Jesteś właścicielem dowolnego obiektu, który tworzysz
Przez wywołanie metody, której nazwa zaczyna się od
alloc
,new
,copy
lubmutableCopy
. Na przykład:NSObject *object1 = [[NSObject alloc] init]; NSObject *object2 = [NSObject new]; NSObject *object3 = [object2 copy];
Oznacza to, że jesteś odpowiedzialny za zwolnienie tych obiektów, gdy skończysz z nimi.
Możesz przejąć na własność obiekt za pomocą zachowaj
Aby przejąć na własność obiekt, wywołujesz metodę zachowania.
Na przykład:
NSObject *object = [NSObject new]; // object already has a retain count of 1 [object retain]; // retain count is now 2
Ma to sens tylko w niektórych rzadkich sytuacjach.
Na przykład, jeśli zaimplementujesz moduł dostępu lub metodę init, aby przejąć własność:
- (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; }
Kiedy już go nie potrzebujesz, musisz zrzec się prawa własności do posiadanego obiektu
NSObject* object = [NSObject new]; // The retain count is now 1 [object performAction1]; // Now we are done with the object [object release]; // Release the object
Nie możesz zrezygnować z własności przedmiotu, którego nie jesteś właścicielem
Oznacza to, że gdy nie przejmiesz własności obiektu, nie zwolnisz go.
Autoreleasepool
Pula autorelease jest blokiem kodu, który uwalnia każdy obiekt w bloku, który otrzymał komunikat autorelease.
Przykład:
@autoreleasepool { NSString* string = [NSString stringWithString:@"We don't own this object"]; }
Stworzyliśmy ciąg bez przejęcia własności. Metoda
NSString
stringWithString:
musi upewnić się, że łańcuch został poprawnie zwolniony, gdy nie jest już potrzebny. Zanim metoda zwróci nowo utworzony ciąg wywołuje metodę autorelease, więc nie musi przejmować własności ciągu.Oto jak implementowany jest
stringWithString:
:+ (NSString *)stringWithString:(NSString *)string { NSString *createdString = [[NSString alloc] initWithString:string]; [createdString autorelease]; return createdString; }
Konieczne jest użycie bloków autoreleasepool, ponieważ czasami masz obiekty, których nie jesteś właścicielem (czwarta zasada nie zawsze ma zastosowanie).
Automatyczne liczenie referencji automatycznie zajmuje się regułami, więc nie musisz.