Шаблоны высвобождения объекта Objective-c - PullRequest
1 голос
/ 16 августа 2011

Я столкнулся с незнакомым кодом управления памятью Objective-c. В чем разница между:

// no property declared for myMemberVariable in interface
id oldID = myMemberVariable;
myMemberVariable = [MyMemberVariable alloc] init];
[oldID release];

и

// (nonatomic, retain) property is declared for myMemberVariable in interface
self.myMemberVariable = [[MyMemberVariable alloc] init];

Спасибо!

Ответы [ 3 ]

4 голосов
/ 16 августа 2011

Второе технически неверно, но первое, вероятно, происходит от кого-то, кто еще использует синтаксис свойства Objective-C 2.0. Он был добавлен сравнительно недавно, если вы являетесь давним разработчиком OS X (или даже более продолжительным разработчиком NextStep / OS X), поэтому вы видите людей, которые не используют его, не получая никакой выгоды или вреда от этого.

Итак, первое в основном совпадает с:

[myMemberVariable release];
myMemberVariable = [[MyMemberVariable alloc] init];

Учитывая, что у вас есть свойство 'retain', правильная версия с установщиком должна быть:

// this'll be retained by the setter, so we don't want to own what we pass in
self.myMemberVariable = [[[MyMemberVariable alloc] init] autorelease];
3 голосов
/ 16 августа 2011

В первом примере у вас есть переменная экземпляра. Во втором - свойство с автоматическими атрибутами управления памятью (как указано в сохранении).

В первом примере вы выделяете объект, присваиваете его переменной экземпляра, а затем освобождаете его. Также кажется, что вы также вытекаете объект, который был ранее ему назначен, так как вы явно не освобождаете его. (Может быть, он выпущен автоматически, не могу сказать здесь).

Во втором примере вы выделяете объект и присваиваете его свойству, которое его сохраняет. Это означает, что вы потеряете его, если не будете явно освобождать / автоматически выпускать его.

self.myMemberVariable = [[[MyMemberVariable alloc] init] autorelease];

или

MyMemberVariable *m = [[MyMemberVariable alloc] init];
self.myMemberVariable = m;
[m release];

Гораздо лучше использовать свойства, поскольку вы получаете (большинство) управление памятью бесплатно. Например, вам не нужно беспокоиться об освобождении ссылки перед назначением новой.

1 голос
/ 16 августа 2011

Первая форма не использует свойства.Я не вижу веской причины не делать этого:

[myMemberVariable release];
myMemberVariable = [[MyClass alloc] init];

Поскольку старое значение определенно не совпадает с новым, поэтому нет никакой вероятности, что какое-либо старое значение будет выпущено, прежде чем оно может быть сохранено.снова.

Свойства имеют то преимущество, что в новых компиляторах они синтезируются компилятором и просто делают правильные вещи, то есть они знают, как сохранить новое и освободить старое значение, если тип равен единице.это должно быть сохранено или скопировано.Это не обязательно для таких типов, как int, float и т. Д., Так как это простые типы значений.

Другими словами, если вы используете точечную нотацию для себя или для другого объекта, вы получаете доступ к свойствуи фактически вызывают либо методы получения, либо установки, в зависимости от направления назначения.

Если вы обращаетесь к ivar (переменная-член) напрямую, у вас нет защиты от свойства, и вам придется самостоятельно сохранять / освобождать код.

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

...