Я устанавливаю свойства в ноль в dealloc при использовании ARC? - PullRequest
123 голосов
/ 26 октября 2011

Я пытаюсь научиться автоматическому подсчету ссылок в iOS 5. Теперь первая часть этого вопроса должна быть простой:

  1. Правильно ли я делаю НЕ нужно писать явные операторы release-свойства в моем dealloc при использовании ARC?Другими словами, верно ли, что следующее НЕ нуждается в явном освобождении?

    @interface MyClass : NSObject
    @property (strong, nonatomic) NSObject* myProperty;
    @end
    
    @implementation MyClass
    @synthesize myProperty;
    @end
    
  2. Мой следующий и более важный вопрос возникает из строки в Переход к примечаниям к выпуску ARC document:

    Вам не нужно (в действительности нельзя) освобождать переменные экземпляра, но вам может потребоваться вызвать [self setDelegate: nil] для системных классови другой код, который не скомпилирован с использованием ARC.

    Возникает вопрос: как узнать, какие системные классы не скомпилированы с ARC?Когда я должен создать свой собственный dealloc и явно установить сильно сохраняющие свойства в nil?Должен ли я предполагать, что для всех классов инфраструктуры NS и UI, используемых в свойствах, требуются явные освобождения?

Существует множество информации о SO и других местах о методах освобождения ивара поддержки свойства при использовании руководства.отслеживание ссылок, но относительно мало об этом при использовании ARC.

Ответы [ 2 ]

197 голосов
/ 26 октября 2011

Краткий ответ : нет, вам не нужно указывать свойства в dealloc в ARC.

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

В MRR вы должны выпустить ivars . Обнуление свойств означает вызов сеттеров, которые могут вызывать код, который он не должен касаться в dealloc (например, если ваш класс или подкласс переопределяет сеттер). Точно так же это может вызвать уведомления KVO. Вместо этого освобождение ивара позволяет избежать нежелательного поведения.

В ARC система автоматически выпускает любые ivars для вас, поэтому, если это все, что вы делаете, вам даже не нужно внедрять dealloc. Однако, если у вас есть не-объектные ивы, требующие особой обработки (например, выделенные буферы, необходимые для free()), вам все равно придется иметь дело с таковыми в dealloc.

Кроме того, если вы установили себя в качестве делегата каких-либо объектов, вы должны отменить это отношение в dealloc (это немного о вызове [obj setDelegate:nil]). Замечание о том, как делать это на классах, которые не скомпилированы с ARC, - это дань слабым свойствам. Если класс явно помечает свое свойство delegate как weak, то вам не нужно этого делать, потому что природа слабых свойств означает, что он прекратит работу для вас. Однако, если свойство помечено assign, вы должны обнулить его в вашем dealloc, в противном случае класс останется с висящим указателем и, скорее всего, потерпит крах, если попытается отправить сообщение своему делегату. Обратите внимание, что это относится только к неподдерживаемым отношениям, таким как делегаты.

1 голос
/ 11 июня 2014

Просто чтобы дать противоположный ответ ...

Краткий ответ : нет, вам не нужно обнулять автоматически синтезированные свойства в dealloc в ARC. И вам не нужно использовать сеттер для тех, кто в init.

Длинный ответ : Вы должны исключить пользовательские синтезированные свойства в dealloc, даже в ARC. И вы должны использовать сеттер для тех, кто в init.

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

Возможный установщик таймера:

-(void)setTimer:(NSTimer *)timer
{
    if (timer == _timer)
        return;

    [timer retain];
    [_timer invalidate];
    [_timer release];
    _timer = timer;
    [_timer fire];
}

Возможный установщик для просмотра прокрутки, просмотра таблицы, веб-просмотра, текстового поля, ...:

-(void)setScrollView:(UIScrollView *)scrollView
{
    if (scrollView == _scrollView)
        return;

    [scrollView retain];
    [_scrollView setDelegate:nil];
    [_scrollView release];
    _scrollView = scrollView;
    [_scrollView setDelegate:self];
}

Возможный установщик для свойства KVO:

-(void)setButton:(UIButton *)button
{
    if (button == _button)
        return;

    [button retain];
    [_button removeObserver:self forKeyPath:@"tintColor"];
    [_button release];
    _button = button;
    [_button addObserver:self forKeyPath:@"tintColor" options:(NSKeyValueObservingOptions)0 context:NULL];
}

Тогда вам не нужно дублировать код для dealloc, didReceiveMemoryWarning, viewDidUnload, ..., и ваша собственность может быть безопасно обнародована. Если вы беспокоитесь о свойствах nil out в dealloc, то, возможно, пришло время снова проверить ваши установщики.

...