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

Я начинаю лучше понимать управление памятью в Objective-C, но я чего-то не понимаю. Это объявление свойства:

@property (nonatomic, retain)UILabel *myLabel;

и это его невидимый синтезированный сеттер (я думаю):

- (void)setMyLabel:(UILabel *)newValue {
    if(myLabel != newValue) {
        [myLabel release];
        myLabel = [newValue retain];
    }
}

Это избавляет вас от всей работы по сохранению и прочему каждый раз, но, скажем, я устанавливаю свое свойство в первый раз, оно еще не выделено, поэтому его счетчик ссылок равен 0, верно? Так что я делаю

UILabel *tempLabel = [[UILabel alloc] init];
self.myLabel = tempLabel;
[tempLabel release];

Я не совсем уверен, что там происходит, когда он ничего не выпускает, но скажем, что свойство уже имеет значение, и мы его устанавливаем. В сеттере сначала он освобождается. Так разве это не заставляет его исчезнуть? Если его счетчик ссылок равен единице, а затем в установщике он освобождается, как он остается, чтобы установить сохраненное новое значение?

Спасибо!!


person mk12    schedule 31.07.2009    source источник


Ответы (3)


Я думаю, вы путаете объекты и ссылки. Свойство — это ссылка на объект, а не сам объект. Когда вы устанавливаете или сбрасываете свойство, оно отправляет удержания и освобождения объектам, на которые оно указывает, но сама ссылка является частью объекта, в котором находится свойство (в данном случае self).

Может быть полезно прочитать о таких вещах, как указатели и lvalues.

person Louis Gerbarg    schedule 31.07.2009

Начальное значение myLabel равно нулю, поэтому ваше первое присвоение свойства, т.е.

self.myLabel = tempLabel;

выпустит nil, т.е. [nil release]. В Objective C отправка сообщения на nil невозможна, так что ничего не получится.

Точно так же в вашем методе Dealloc у вас должно быть:

[myLabel release];

Что освободит myLabel, если свойство когда-либо было назначено, уравновешивая [newValue keep] в установщике. Если свойство никогда не назначалось, то оно все равно будет нулевым, и снова [нулевой выпуск] будет неактивным.

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

Объект «исчезнет» (т. е. будет освобожден), когда все права собственности на него будут потеряны. То есть, когда (или вскоре после этого) все вызовы alloc/copy/new были сбалансированы с вызовами release/autorelease.

person Peter N Lewis    schedule 01.08.2009

Я также относительно новичок в Objective-C, но хотел бы попытаться ответить на этот вопрос, чтобы подтвердить свое понимание.

скажем, я установил свое свойство в первый раз, оно еще не было выделено, поэтому его счетчик ссылок равен 0, верно?

Да, количество сохранений равно 0.

В сеттере сначала он освобождается. Так разве это не заставляет его исчезнуть?

Он вычитает 1 из счетчика удержания myLabel. Если счетчик сохранения myLabel достигает 0, данные или объект, на который указывает переменная myLabel, будут освобождены из памяти.

Если его счетчик ссылок равен единице, а затем в установщике он освобождается, как он остается, чтобы установить сохраненное новое значение?

В этом случае данные, на которые указывает myLabel, будут освобождены (количество сохранений будет равно 0), а myLabel будет указывать на ноль (пусто). Переменная устанавливается в классе и всегда будет доступна для приема сообщений этому установщику, поэтому новые данные могут быть назначены myLabel независимо от того, равно ли счетчику сохранения myLabel 0 или 100.

person Greg    schedule 31.07.2009
comment
С технической точки зрения лучше не думать об абсолютном количестве удержаний, а вместо этого подумать о том, есть ли у вас доля собственности в объекте. Если счетчик сохранения объекта достигает 0, он освобождается. Объекты с автоматическим выпуском (которые могут сохранять количество 1, а затем уменьшаться до 0) отличаются от того, что вы объясняете в своем первом пункте. И, как указывает Луис, ивары (переменные/ссылки) не имеют счетчика сохранения, в отличие от объектов. - person Quinn Taylor; 01.08.2009
comment
Вы должны опубликовать это как комментарий к вопросу или как новый вопрос. - person Quentamia; 29.07.2011