Пользовательские сделка и ARC (Objective-C)

208

В моем маленьком приложении для iPad есть функция «переключения языка», в которой используется наблюдатель. Каждый контроллер представления регистрируется во время своего наблюдателя viewDidLoad:.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [observer registerObject:self];
}

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

Это работает очень хорошо, за исключением случаев, когда у меня есть контроллеры представления в TabBarController. Это происходит потому, что при загрузке панели вкладок она выбирает значки вкладок из своих дочерних контроллеров без инициализации представлений, поэтому viewDidLoad:не вызывается, поэтому эти контроллеры представлений не получают уведомлений об изменении языка. Из-за этого я переместил свои registerObject:вызовы в initметод.

Когда я viewDidLoad:регистрировался у своего наблюдателя, я viewDidUnload:отменял регистрацию. Поскольку я сейчас регистрируюсь init, имеет смысл отменить регистрацию dealloc.

Но вот моя проблема. Когда я пишу:

- (void) dealloc
{
    [observer unregisterObject:self];
    [super dealloc];
}

Я получаю эту ошибку:

ARC запрещает явную отправку сообщения 'dealloc'

Так как мне нужно позвонить, [super dealloc]чтобы убедиться, что суперклассы убираются должным образом, но ARC запрещает это, я застрял. Есть ли другой способ получить информацию, когда мой объект умирает?

нику
источник
Как примечание: такая ситуация может привести к утечке памяти, которая не будет отображаться в инструменте Leaks. Если dataModel сохраняет ссылку на наблюдателя (что является предметом по умолчанию в ARC, даже для ivars), dealloc никогда не будет вызван, так как счетчик хранения будет больше нуля. Таким образом, вам, возможно, придется вручную отменить регистрацию наблюдателя, чтобы сначала можно было вызывать dealloc.
Блажей Чапп
Я реализовал нечто подобное для правого и левого опций. Единственный VC, которому нужно это сообщение, это отображаемый в данный момент. Другие смотрят на модель в viewDidLoad или viewDidAppear, чтобы внести изменения в интерфейс. Может быть, что-то подобное будет работать лучше.
Даг Уоткинс
@BlazejCzapp, так как он использует UITabBarController, и, скажем, UITabBarController всегда будет содержать ссылку на зарегистрированный контроллер (как я полагаю, в случае его «дочерних» контроллеров), утечка памяти все еще будет проблемой? Я не вижу, когда будет зарегистрирован зарегистрированный контроллер. Спасибо
Объектив

Ответы:

419

При использовании ARC вы просто не вызываете [super dealloc]явно - компилятор обрабатывает его для вас (как описано в документе Clang LLVM ARC, глава 7.1.2 ):

- (void) dealloc
{
    [observer unregisterObject:self];
    // [super dealloc]; //(provided by the compiler)
}
джастин
источник
4
Если представление содержит ссылку на наблюдателя, а наблюдатель содержит ссылку на представление, то у нас есть циклическая ссылка. Таким образом, счетчик ссылок представления больше 0 и deallocникогда не вызывается. Имеет ли смысл звонить [observer unregisterObject:self]в dealloc? Чего мне не хватает?
user443854
вот хочешь работать. потому что сам наблюдатель держит ссылку на контроллер. это предотвратит колл-колл в первую очередь
Хасан