Политика управления памятью
Базовая модель, используемая для управления памятью в считаемой на ссылку среде, предоставлена комбинацией методов, определенных в NSObject
протокол и соглашение о присвоении имен стандартного метода. NSObject
класс также определяет метод, dealloc
, когда объект освобожден, это вызывается автоматически. Эта статья описывает все основные правила, которые Вы должны знать для управления памятью правильно в программе Какао и обеспечиваете некоторые примеры корректного использования.
Правила управления основной памятью
Модель управления памятью основывается на монопольном использовании объекта. Любой объект может иметь одного или более владельцев. Пока объект имеет по крайней мере одного владельца, он продолжает существовать. Если объект не имеет никаких владельцев, система во время выполнения уничтожает его автоматически. Для проверки ясно при владении объектом и когда Вы не делаете, Какао устанавливает следующую политику:
Вам принадлежит любой объект, который Вы создаете
Вы создаете объект с помощью метода, имя которого начинается с «выделения», «нового», «копия» или «mutableCopy» (например,
alloc
,newObject
, илиmutableCopy
).Можно взять владение объектного использования, сохраняют
Полученный объект, как обычно гарантируют, останется допустимым в методе, в котором он был получен, и тот метод может также безопасно возвратить объект своему invoker. Вы используете
retain
в двух ситуациях: (1) В реализации метода доступа илиinit
метод, для взятия владения объекта Вы хотите сохранить как значение свойства; и (2) Для препятствования объекту быть лишенным законной силы как побочный эффект некоторой другой работы (как объяснено в Избегают Вызывать Освобождение Объектов, которые Вы Используете).Когда Вам больше не нужен он, необходимо оставить владение объекта, которым Вы владеете
Вы оставляете владение объекта путем отправки ему a
release
обменивайтесь сообщениями илиautorelease
сообщение. В терминологии Какао, оставляя владение объекта поэтому обычно упоминается как «выпуск» объекта.Вы не должны оставлять владение объекта, которым Вы не владеете
Это - просто заключение предыдущих правил политики, утвердил явно.
Простой пример
Для иллюстрирования политики рассмотрите следующий фрагмент кода:
{ |
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]; |