Политика управления памятью

Базовая модель, используемая для управления памятью в считаемой на ссылку среде, предоставлена комбинацией методов, определенных в NSObject протокол и соглашение о присвоении имен стандартного метода. NSObject класс также определяет метод, dealloc, когда объект освобожден, это вызывается автоматически. Эта статья описывает все основные правила, которые Вы должны знать для управления памятью правильно в программе Какао и обеспечиваете некоторые примеры корректного использования.

Правила управления основной памятью

Модель управления памятью основывается на монопольном использовании объекта. Любой объект может иметь одного или более владельцев. Пока объект имеет по крайней мере одного владельца, он продолжает существовать. Если объект не имеет никаких владельцев, система во время выполнения уничтожает его автоматически. Для проверки ясно при владении объектом и когда Вы не делаете, Какао устанавливает следующую политику:

Простой пример

Для иллюстрирования политики рассмотрите следующий фрагмент кода:

{
    Person *aPerson = [[Person alloc] init];
    // ...
    NSString *name = aPerson.fullName;
    // ...
    [aPerson release];
}

Объект Лица создается с помощью alloc метод, таким образом, это впоследствии отправляется a release обменивайтесь сообщениями, когда это больше не будет необходимо. Имя лица не получено с помощью любого из методов владения, таким образом, оно не отправляется a release сообщение. Заметьте, тем не менее, что пример использует release вместо autorelease.

Используйте автовыпуск для Отправки Задержанного выпуска

Вы используете autorelease когда необходимо отправить задержанный release сообщение — обычно при возврате объекта из метода. Например, Вы могли реализовать fullName метод как это:

- (NSString *)fullName {
    NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@",
                                          self.firstName, self.lastName] autorelease];
    return string;
}

Вам принадлежит строка, возвращенная alloc. Для соблюдения правил управления памятью необходимо оставить владение строки перед потерей ссылки на него. Если Вы используете release, однако, строка будет освобождена, прежде чем она будет возвращена (и метод возвратил бы недопустимый объект). Используя autorelease, Вы показываете, что хотите оставить владение, но Вы позволяете вызывающей стороне метода использовать возвращаемую строку, прежде чем это будет освобождено.

Вы могли также реализовать fullName метод как это:

- (NSString *)fullName {
    NSString *string = [NSString stringWithFormat:@"%@ %@",
                                 self.firstName, self.lastName];
    return string;
}

Соблюдая основные правила, Вам не принадлежит строка, возвращенная stringWithFormat:, таким образом, можно безопасно возвратить строку из метода.

Посредством контраста следующая реализация является неправильной:

- (NSString *)fullName {
    NSString *string = [[NSString alloc] initWithFormat:@"%@ %@",
                                         self.firstName, self.lastName];
    return string;
}

Согласно соглашению о присвоении имен, нет ничего, чтобы обозначить что вызывающая сторона fullName методу принадлежит возвращаемая строка. Вызывающая сторона поэтому не имеет никакой причины выпустить возвращаемую строку, и это будет таким образом пропущено.

Вам не принадлежат объекты, возвращенные ссылкой

Некоторые методы в Какао указывают, что объект возвращается ссылкой (т.е. они берут параметр типа ClassName ** или id *). Общий образец должен использовать NSError объект, содержащий информацию об ошибке, если Вы происходите, как проиллюстрировано initWithContentsOfURL:options:error: (NSData) и initWithContentsOfFile:encoding:error: (NSString).

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

NSString *fileName = <#Get a file name#>;
NSError *error;
NSString *string = [[NSString alloc] initWithContentsOfFile:fileName
                        encoding:NSUTF8StringEncoding error:&error];
if (string == nil) {
    // Deal with error...
}
// ...
[string release];

Реализуйте dealloc для Отказа от Владения Объектов

NSObject класс определяет метод, dealloc, это вызывается автоматически, когда объект не имеет никаких владельцев, и в отношении его памяти предъявляют претензии — в терминологии Какао, это «освобождено» или «освобождено».. Роль dealloc метод должен освободить собственную память объекта, и избавляться от любых ресурсов, которые это содержит, включая владение любых переменных экземпляра объекта.

Следующий пример иллюстрирует, как Вы могли бы реализовать a dealloc метод для класса Лица:

@interface Person : NSObject
@property (retain) NSString *firstName;
@property (retain) NSString *lastName;
@property (assign, readonly) NSString *fullName;
@end
 
@implementation Person
// ...
- (void)dealloc
    [_firstName release];
    [_lastName release];
    [super dealloc];
}
@end

Базовая основа использует подобные но различные правила

Существуют подобные правила управления памятью для Базовых объектов Основы (см. Руководство по программированию управления памятью для Базовой Основы). Соглашения о присвоении имен для Какао и Базовой Основы, однако, отличаются. В частности Базовая Основа Создают Правило (см. Создать Правило), не применяется к методам тот Objective C возврата объекты. Например, в следующем фрагменте кода, Вы не ответственны за отказ от владения myInstance:

MyClass *myInstance = [MyClass createInstance];