Установите делегатов на ноль под ARC? - программирование
Подтвердить что ты не робот

Установите делегатов на ноль под ARC?

Я пишу приложения iOS с помощью ARC и настраиваю iOS 5 +.

Предположим, что я пишу пользовательский объект вида, обладающий свойством delegate. При объявлении свойства делегирования я делаю его слабым, чтобы избежать цикла сохранения, так что, когда уничтожается фактический объект-делегат (контроллер), мое пользовательское представление также будет уничтожено следующим образом:

@interface MyCustomView : UIView

@property (nonatomic, weak) id<MyCustomViewDelegate> delegate;

@end

Все хорошо.

Итак, теперь я пишу объект контроллера и ссылается на два объекта представления: мое пользовательское представление и представление UIKit, поставляемое Apple, оба из которых объявляют свойства делегата, а контроллер - делегат для обоих Просмотры. Может быть, это выглядит примерно так:

@interface MyViewController : UIViewController <MyCustomViewDelegate, UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, strong) MyCustomView *customView;
@property (nonatomic, strong) UITableView *tableView;

@end

@implementation MyViewController

- (void)viewDidLoad
{
    self.customView.delegate = self;
    self.tableView.dataSource = self;
    self.tableView.delegate = self;
}

@end

Мой вопрос заключается в следующем: нужно ли переопределить dealloc, чтобы установить либо или оба делегата в nil?

Я имею в виду, как я понимаю, свойство делегирования представления UIKit (в данном случае tableView) на самом деле не объявлено как слабая ссылка, а скорее ссылкой __unsafe_unretained, для обратной совместимости с не-ARC-версия iOS. Поэтому, возможно, мне нужно написать

- (void)dealloc
{
    _tableView.dataSource = nil;
    _tableView.delegate = nil;
}

Теперь, если мне нужно переопределить dealloc, мне все равно не нужно устанавливать _customView.delegate = nil, правильно? Поскольку это было объявлено (мной) как слабое задание, поэтому оно должно быть установлено на nil автоматически при уничтожении MyViewController.

Но, с другой стороны, я не нацелен на не-ARC-версии iOS, и не намерен. Так что, возможно, мне вообще не нужно переопределять dealloc?

4b9b3361

Ответ 1

Настройка слабых делегатов на нуль - это, как правило, хорошая идея, если вы не знаете, что вам не нужно. Для UITableView и UIScrollView у меня возникли сбои в предыдущих версиях iOS со следующими шагами (это может помочь запустить с включенными зомби):

  • Прокрутите очень быстро.
  • Нажмите кнопку "Готово" или кнопку "Назад" или что-то еще, чтобы закрыть VC.

Это похоже на то, что анимация прокрутки сохраняет ссылку на представление, поэтому представление переходит в VC. Он вылетает при отправке события прокрутки.

Я также видел сбои после отклонения VC, содержащего UIWebView во время загрузки запроса, где просто установка делегата на nil была недостаточной (я думаю, что обходной путь состоял в вызове [webView loadRequest:nil]).

Ответ 2

Если единственным сильным ссылкой на указанный tableView является ваш единственный контроллер MyViewController, вам не нужно вручную устанавливать UITableViewDelegate или UITableViewDataSource на nil.

Причина в том, что после вызова метода dealloc на вашем MyViewController табличное представление также будет уничтожено вместе с контроллером (то есть еще раз, пока единственной ссылкой на него является ваш единственный контроллер MyViewController).

Если у вас есть другие сильные ссылки на эту таблицу, например, другие контроллеры, тогда будет возможно, что табличное представление может существовать дольше, чем класс MyViewController. В таком случае потребовалось бы установить UITableViewDelegate и UITableViewDataSource в nil в методе dealloc MyViewController, потому что, как вы упомянули, эти свойства НЕ являются слабыми ссылками и автоматически не будет установлен на nil.

Однако такая ситуация довольно редко встречается в моем опыте.

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

Смотрите также этот пост:

В методе dealloc установлено любое делегирование нуль или не требуется

Ответ 3

Единственная причина, по которой вы хотите явно установить delegate и dataSource в nil, - это то, что customView или tableView могут выйти из контроллера просмотра. Установка их в nil будет защищать от delegate или dataSource, ссылающихся на освобожденный объект.

Если customView и tableView будут освобождены вместе с контроллером представления, нет необходимости выходить из delegate и dataSource.