Управление памятью iPhone - PullRequest
       2

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

3 голосов
/ 12 декабря 2010

Есть несколько концепций управления памятью iPhone, которые запутали меня, поэтому я надеялся, что кто-то сможет прояснить это.

(a) Скажем, что я вызываю функцию, которая возвращает изображение, иЯ хочу сохранить это возвращенное изображение в переменной, чтобы я мог назначить его различным другим переменным без необходимости повторного вызова функции генерации изображения каждый раз.На данный момент я делаю следующее:

UIImage *storedImage = [someFunction returnImage];

и, поскольку storedImage не alloc 'ed, я не освобождаю переменную.

Однако я должен быть явноalloc взамен и освобождая UIImage вместо этого?

UIImage *storedImage = [[UIImage alloc] init];
storedImage = [someFunction returnImage];
...do stuff...
[storedImage release];

Что означает выполнение прямого присваивания без alloc, а не alloc, переменной и затем присвоения?

(b) В методе init для различных классов я устанавливаю переменные экземпляра.На данный момент я делаю следующее:

self.arrayVariable = [[NSMutableArray alloc] init];

Однако я видел, как другие выполняют это задание следующим образом:

theArrayVariable = [[NSMutableArray alloc] init];
self.arrayVariable = theArrayVariable;
[theArrayVariable release];

или

theArrayVariable = [[NSMutableArray alloc] init];
arrayVariable = theArrayVariable;
[theArrayVariable release];

.... что такое же, как указано выше, но без self.

В чем разница между тремя методами и какой лучше использовать?

Ответы [ 3 ]

3 голосов
/ 12 декабря 2010

Что касается возврата объектов из методов, вы всегда должны возвращать автоматически освобожденный объект из любого метода, который не начинается с имени alloc, new или содержит copy. Это определено в политике владения объектом Apple , которая гласит, что вы являетесь владельцем любого создаваемого вами объекта («создание» определяется как объект, которому вы отправили retain, или использовал любое из вышеупомянутых сообщений для получить объект), и что вы несете ответственность за отказ от владения этим объектом, отправив ему сообщение release или autorelease.

Первый метод, использующий self, использует установщик свойства , чтобы установить переменную экземпляра в качестве аргумента (в данном случае независимо от того, что находится в RHS назначения). Это будет делать все, что вы указали в объявлении @property (например, если вы указали retain, установщик будет retain новое значение и release старое значение).

Второй метод устанавливает указатель на NSMutableArray и передает его вашему установщику свойства через self, который, скорее всего, retain, в результате чего счетчик ссылок достигает 2, так как объект был ранее alloc -едан, поэтому вам нужно release его после этой строки, чтобы вернуть его к 1.

Третий метод не будет работать, потому что вы releasing объект с числом ссылок 1 в точке вызова release. Как ты так спрашиваешь? Итак, первая строка устанавливает указатель на объект alloc, затем напрямую присваивает его переменной вашего экземпляра, которая просто укажет ivar на тот же объект, на который указывает theArrayVariable , Затем тот же объект, на который указывает theArrayVariable, получает метод release, который эффективно снизит счетчик ссылок вашего ивара и получателя до 0. На этом этапе обе ваши переменные экземпляра и theArrayVariable будут освобождены.

1 голос
/ 12 декабря 2010

а) Код, который вы дали, не делает то, что вы хотите. Когда ты сказал

<code>UIImage *storedImage = [someFunction returnImage];
someFunction возвращает объект изображения, но это не гарантирует, что объект изображения будет жить вечно. Если вы не хотите, чтобы изображение было освобождено без вашего разрешения в будущем, вы должны получить его, позвонив в службу поддержки следующим образом:
UIImage *storedImage = [[someFunction returnImage] retain];

Так что теперь этот объект изображения принадлежит и someFunction, и вам. Когда вы заканчиваете работу с этим объектом, вы освобождаете его, вызывая release. Когда и someFunction, и вы вызываете release для этого объекта, он будет освобожден (конечно, если он не принадлежит другому владельцу).

В другом сегменте кода вы создаете объект изображения и владеете им, вызывая

UIImage *storedImage = [[UIImage alloc] init];

Но тогда вы теряете его ссылку, присваивая новый объект указателю storeImage, вызывая someFunction. В этой ситуации созданный вами образ не освобождается, а продолжает жить где-то в памяти.

1 голос
/ 12 декабря 2010

а) Общее правило для target-c состоит в том, что если вы его распределяете, вы должны его освободить. В первом примере метод возвращает указатель на объект, который уже существует, и поэтому вы не несете ответственности за его освобождение. Во втором примере первое подобное бессмысленно, поскольку вы не используете выделенную память для сохраненного изображения. Это может вызвать утечку памяти.

б) Первые два - просто стилистические различия, без различий в результатах. В них вам останется arrayVariable, указывающая на объект, возвращаемый [[NSMutableArray alloc] init]; (при условии, что вы сохраните в объявлении @property) и вы должны освободить его в методе -dealloc. Как указано выше, третий не будет работать, потому что вы просто выдаваете указатель.

Вот полезная статья для понимания управления памятью в obj-c: http://memo.tv/memory_management_with_objective_c_cocoa_iphone

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...