Когда «освобождать» после установки свойства / экземпляра переменной - PullRequest
0 голосов
/ 29 сентября 2011

У нас объявлено свойство:

@property (retain) MyClass *myProperty;

В чем отличие этого примера от Apple: Code:

MyClass *aux = [[MyClass alloc] init];
myProperty = aux;
[aux release];

и этого:

myProperty = [[MyClass alloc] init];

Отредактировано:

Исходный код должен был быть таким:

MyClass *aux = [[MyClass alloc] init];
self.myProperty = aux;
[aux release];

Это была моя ошибка, но так как многие ответы охватили тему, я оставил исходный код.

Ответы [ 4 ]

3 голосов
/ 29 сентября 2011

Как правило, это правильный способ присвоить свойству новое значение, которое вы создали.

MyClass *aux = [[MyClass alloc] init]; // new value retain count 1
self.myProperty = aux; // new value retain count 2; IMPORTANT: old value retain count decremented
[aux release]; // new value retain count 1, correct since it's retained by self

Это допустимо в методе init.

myProperty = [[MyClass alloc] init]; // new value retain count 1; there was no old value since the object just init'ed

Код, который вы опубликовали, неверен.

MyClass *aux = [[MyClass alloc] init]; // new value retain count 1
myProperty = aux; // new value retain count 1
[aux release]; // new value retain count 0!! deallocated; myProperty points to invalid memory

Следующий код немного неверен.

self.myProperty = [[MyClass alloc] init]; // new value retain count 1 for alloc + 1 for assigned to retain property
[self.myProperty release]; // normally new value retain count 1, correct

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

1 голос
/ 29 сентября 2011

Во-первых, просто чтобы немного уточнить, что означает объявление свойства, я немного объясню.

Когда вы объявляете свойство, вы на самом деле объявляете два метода, метод get и метод set для этого конкретного атрибута класса.Когда вы объявляете свойство как retain, вы фактически говорите, что когда вы устанавливаете это свойство с помощью метода setter, оно будет сохранено.В основном это означает, что его счетчик будет увеличен.

Чтобы установить атрибут класса с помощью объявленного свойства, вы можете использовать синтаксис точки, например, self.myProperty, или метод установки, например, -(void)setMyProperty:(MyClass*)newMyClass,

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

Теперь,

MyClass *aux = [[MyClass alloc] init];
myProperty = aux;
[aux release];
  1. Вы выделяете объект MyClass, теперь этот объект имеет количество сохраненных единиц 1.
  2. Вы назначаете его своему атрибуту класса (без использования свойства), чтобы сохранитьколичество равно 1.
  3. Вы освобождаете этот объект, так что его счет сохранения равен 0, и он освобождается.

myProperty = [[MyClass alloc] init];

  1. Вы выделяетеMyClass объект (он имеет счетчик 1) и присвойте ему свой атрибут класса myProperty.

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

1 голос
/ 29 сентября 2011
self.myProperty = [[MyClass alloc] init];  // this will leak
myProperty = [[MyClass alloc] init];  // this will NOT leak

Утечка первой строки, потому что он использует установщик свойства для назначения нового объекта, а свойство имеет модель памяти retain.Таким образом, в дополнение к alloc в присваивании вы получаете сохранение от установщика свойства.

Однако вторая строка не будет просачиваться, поскольку она использует не установщик свойства, а закрытую переменную, стоящую за ним.Вообще говоря, вы хотите использовать установщик везде, кроме init.

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

self.myProperty = [[[MyClass alloc] init] autorelease];  // Yeah, no leak now

Если вы действительно хотите обернуть вокруг него голову, переопределенный установщик может выглядеть примерно так:

- (void) setMyProperty:(MyClass*)newMyProperty
{
   MyClass *oldValue = _myProperty;
   // replace retain with copy if you want copy to be memory model
   _myProperty = [newMyProperty retain];   
   [oldValue release];  // release last in case newMyProperty == oldValue

   [...] // super cool setter behavior here
}
0 голосов
/ 29 сентября 2011

В первом случае myProperty имеет retainCount 0.
Во втором случае myProperty имеют retainCount 1.
Если вы будете использовать self.myProperty = aux в первом случае, тогда retainCount of aux и myProperty будет 1.

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