Поиск…


Автоматический подсчет ссылок

С автоматическим подсчетом ссылок (ARC) компилятор вставляет инструкции retain , release и autorelease там, где они необходимы, поэтому вам не нужно писать их самостоятельно. Он также пишет для вас методы dealloc .

Пример программы из Manual Memory Management выглядит так: 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"];
}

Вы по-прежнему можете переопределить метод dealloc для очистки ресурсов, которые не обрабатываются ARC. В отличие от использования ручного управления памятью, вы не вызываете [super dealloc] .

-(void)dealloc {
   //clean up
}

Сильные и слабые ссылки

Современный

Слабая ссылка выглядит как одна из них:

@property (weak) NSString *property;
NSString *__weak variable;

Если у вас слабое отношение к объекту, то под капотом:

  • Вы не сохраняете его.
  • Когда он будет освобожден, каждая ссылка на него будет автоматически установлена ​​на nil

По умолчанию ссылки на объекты всегда сильны. Но вы можете явно указать, что они сильны:

@property (strong) NSString *property;
NSString *__strong variable;

Сильная ссылка означает, что, хотя эта ссылка существует, вы сохраняете объект.

Управление памятью вручную

Это пример программы, написанной с ручным управлением памятью. Вы действительно не должны писать свой код, как это, если по какой-то причине вы не можете использовать ARC (например, если вам нужно поддерживать 32-разрядный). В примере избегается нотация @property чтобы проиллюстрировать, как вам приходилось писать геттеры и сеттеры.

@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];
}

Правила управления памятью при использовании ручного подсчета ссылок.

Эти правила применяются только в том случае, если вы используете ручной подсчет ссылок!

  1. У вас есть любой объект, который вы создаете

    Вызвав метод, имя которого начинается с alloc , new , copy или mutableCopy . Например:

    NSObject *object1 = [[NSObject alloc] init];
    NSObject *object2 = [NSObject new];
    NSObject *object3 = [object2 copy];
    

    Это означает, что вы несете ответственность за освобождение этих объектов, когда вы закончите с ними.

  2. Вы можете взять собственность на объект, используя

    Чтобы взять собственность за объект, вы вызываете метод сохранения.

    Например:

    NSObject *object = [NSObject new]; // object already has a retain count of 1
    [object retain]; // retain count is now 2
    

    Это имеет смысл только в некоторых редких ситуациях.

    Например, когда вы реализуете метод доступа или метод init, чтобы получить право собственности:

    - (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. Когда вы больше не нуждаетесь в этом, вы должны отказаться от собственности на свой объект

    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. Вы не должны отказываться от права собственности на объект, который у вас нет.

    Это означает, что когда вы не взяли на себя ответственность за объект, вы его не отпустите.

  5. Autoreleasepool

    Autoreleasepool - это блок кода, который освобождает каждый объект в блоке, который получил сообщение автозапуска.

    Пример:

    @autoreleasepool {
        NSString* string = [NSString stringWithString:@"We don't own this object"];
    }
    

    Мы создали строку без права собственности. Метод NSString stringWithString: должен убедиться, что строка правильно освобождена после того, как она больше не нужна. Перед возвратом метода вновь созданная строка вызывает метод авторекламы, поэтому ему не нужно владеть строкой.

    Так stringWithString: :

    + (NSString *)stringWithString:(NSString *)string {
        NSString *createdString = [[NSString alloc] initWithString:string];
        [createdString autorelease];
        return createdString;
    }
    

    Необходимо использовать блоки autoreleasepool, потому что у вас иногда есть объекты, которыми вы не владеете (четвертые правила не всегда применяются).

    Автоматический подсчет ссылок автоматически учитывает правила, поэтому вам не нужно.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow