Пользовательские сделка и 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

вот хочешь работать. потому что сам наблюдатель держит ссылку на контроллер. это предотвратит колл-колл в первую очередь
— Хасан
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.