Спеціальна угода та 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 забороняє це, я зараз застряг. Чи є інший спосіб отримати інформацію, коли мій предмет помирає?


Як бічна примітка - така ситуація може спричинити витік пам’яті, який не відображатиметься в інструменті «Витоки». Якщо dataModel збереже посилання на спостерігача (що є ARC за замовчуванням, навіть для ivars), транзакція ніколи не буде викликана, оскільки кількість утримуваних даних буде більшим за нуль. Таким чином, вам, можливо, доведеться вручну скасувати реєстрацію спостерігача, щоб в першу чергу викликати транзакцію.
Błażej Czapp

Я реалізував щось подібне для прав і лівих варіантів. Єдиний ВК, який потребує повідомлення, - це відображається в даний час. Інші дивляться на модель в viewDidLoad або viewDidAppear, щоб внести зміни в інтерфейс. Можливо, щось подібне працювало б краще.
Doug Watkins

@BlazejCzapp, оскільки він використовує UITabBarController, і скажімо, UITabBarController завжди матиме посилання на зареєстрований контролер (як, мабуть, це стосується контролерів "дочірніх"), чи буде витік пам'яті все ще залишатися проблемою? Я не бачу, коли буде виділено зареєстрований контролер. Спасибі
Objectif

Відповіді:


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]в угоду? Що я пропускаю?
user443854

ось хочуть роботи. тому що сам спостерігач тримає посилання на контролер. це перешкоджатиме в першу чергу викликати угоду
hasan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.