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

Nowoczesny

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!

  1. Jesteś właścicielem dowolnego obiektu, który tworzysz

    Przez wywołanie metody, której nazwa zaczyna się od alloc , new , copy lub mutableCopy . 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.

  2. 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;
    }
    
  3. 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
    
  4. 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.

  5. 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.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow