Создает ли этот код объективного кода сильный ссылочный цикл?
Я работаю в чужом проекте iOS. ARC (и, насколько мне известно, всегда был) включен. Код завален обработчиками нажатий кнопок, которые создают экземпляр некоторого контроллера представления, устанавливают его делегата на себя, а затем показывают его, например,
- (IBAction)keyButton:(id)sender {
MyViewController *controller = [[MyViewController alloc] init];
controller.delegate = self;
[self.navigationController pushViewController:controller animated:YES];
}
MyViewController показывает виджет вращения для выбора музыкальной клавиши. После выбора пользователь нажимает назад, чтобы использовать выбранную клавишу для создания музыки. Это единственное взаимодействие с пользователем, нет фоновых процессов и т. Д.
В файле MyViewController.h делегат объявляется следующим образом:
@interface MyViewController : UIViewController {
id <ModuleUpdateDelegate> _delegate;
}
@property (nonatomic,strong) id delegate;
У меня есть два вопроса:
- Почему оригинальный автор решил создать новый экземпляр MyViewController при каждом нажатии кнопки?
- Кому принадлежит каждый такой экземпляр? [Когда] это разрушается? Поскольку он содержит строгую ссылку на своего делегата, создает ли текущая реализация цикл строгой ссылки [с каждым нажатием кнопки]?
Мой собственный инстинкт состоит в том, чтобы создать частное свойство MyViewController * в делегате, которое загружается только при первом нажатии кнопки. Тогда я бы сделал свойство делегата в MyViewController слабым вместо сильного, в соответствии с общей рекомендацией. Но, как я уже сказал, текущая реализация довольно распространена, поэтому я опасаюсь что-либо менять, не понимая, как это работает.
Любая помощь приветствуется.
2 ответа
В этом случае не имеет значения, кто MyViewController
сохраняет, имеет значение, кто сохраняет пример MyViewController
,
В коде вы разместили сильную ссылку на MyViewController
проводится self.navigationController
, Как только MyViewController
выскочил, то его счет удержания достигнет 0, и он будет освобожден. Пока controller.delegate
не сохраняет controller
Цикла нет.
Тем не менее, вы должны быть очень осторожны с сильными обратными ссылками (например, такими как делегаты). В случае сомнений используйте инструменты для проверки на наличие циклов или утечек памяти.
Мой совет: будьте осторожны. Превратите сильного делегата в слабого, если это возможно. Даже если сейчас нет цикла сохранения, вы можете легко его создать, не осознавая этого.
Рекомендации делегатов слабы по соглашению.
Обычно вы создаете объект, удерживаете сильную ссылку на него и устанавливаете себя в качестве его делегата. (и указатель на делегат слабый.) Таким образом, существует только сильная ссылка одним способом.
В вашем случае ваш код делает обратное. Объект (MyViewController) создается в локальной переменной, а затем забывается. Свойство делегата класса MyViewController является сильным. Таким образом, нет строгой ссылки на объект MyViewController, но есть сильная ссылка на делегат.
Как говорит Джеффри, у вас сейчас нет цикла сохранения, но если позже вы решите, что вам нужно сохранить указатель на ваш объект MyViewController, вы, вероятно, создадите цикл сохранения.