Кто должен нести ответственность за освобождение параметра сеттера?

Пожалуйста, смотрите код следующим образом:

- (void) setSomeThing:(NSString *) someThingNew
{
     if(someThing!=someThingNew)
     {
         [someThingNew retain];
         [someThing release];
         someThing = someThingNew;
     }
 }

 ... ...
 - (void) dealloc
 {
     [someThing release];
     [super dealloc];
 }
@end

Параметр сеттера someThingNew был retain в методе установки, что означает, что его счет сохранения равен 1.

Здесь вопрос: это someThingNew должен release?

Или потому что someThing а также someThingNew указать на тот же объект, а в dealloc метод someThing был release так someThingNew указать на nil?

3 ответа

Решение

это someThingNew должен выпустить?

Нет, потому что сейчас someThing а также someThingNew указать на тот же адрес. Выпуская someThing в dealloc (и обнуляя это, чтобы быть безопасным, но это для другого вопроса), вы балансируете удержание в сеттере. Все отлично работает! *

* sidenote: экземпляры NSString обычно copy не retain г, в сеттерах, так что не имеет значения, если вы случайно передали NSMutableString к этому.

Всякий раз, когда вызывается ваш метод установки, someThingNew сохраняется, а someThing освобождается. Затем новый адрес someThingNew сохраняется в someThing, в результате чего счетчик остается равным 1.

Это остается для класса, пока сам объект не будет освобожден. Когда вызывается dealloc, освобождается указатель someThingNew, в результате чего счетчик остается равным 0.

Ваш код верен: установщик должен сохранить объект, если вы хотите сделать его "сильной" переменной. Но вы не должны выпускать это: это не область ответственности сеттера. Таким образом, в коде, откуда вы вызываете сеттер, вы будете:

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

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

Пример:

NSAutoreleasePool* pool=[[NSAutoreleasePool alloc]init];
NSString* newString= [[NSMutableString alloc]initWithString: @"Hello"]; // Retain count 1.
[newString autorelease]; // Still 1 as retain count, but it will be decreased
                         // when the pool will be drained.
[object setSomeThing: newString];  // Retain count 2.
[pool drain]; // Retain count 1

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

Копирование объекта

Если вы копируете объект, то способ вызова метода (то есть приведенный выше код) не изменится, он просто изменит реализацию метода. Что-то вроде этого:

- (void) setSomeThing:(NSString *) someThingNew
{
     if(someThing!=someThingNew)
     {
         [someThing release];   // Retain count decreased by 1.
         someThing = [someThingNew copy];  // Retain count 1.
     }
 }

 ... ...
 - (void) dealloc
 {
     [someThing release];
     [super dealloc];
 }
@end
Другие вопросы по тегам