Я устанавливаю свойства nil в dealloc при использовании ARC?

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

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

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

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

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

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

Ответ 1

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

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

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

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

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

Ответ 2

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

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

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

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

Возможный сеттер для таймера:

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

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

Возможный сеттер для scrollview, tableview, webview, textfield,...:

-(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 в dealloc, возможно, вам придется снова проверить свои сеттеры.