Жизненный цикл UINavigationItem

Насколько я понимаю, в документации SDK жизненный цикл UIViewController navigationItem привязан к самому контроллеру, а не к представлению контроллера. т.е. в реализации по умолчанию он создается по запросу и уничтожается с помощью контроллера представления — со всем содержимым, таким как элементы кнопок и titleView. Учитывая, что как элементы кнопок, так и titleView могут быть представлены экземплярами UIView, означает ли это, что после создания эти представления останутся в памяти до тех пор, пока контроллер не будет уничтожен и не проживет все предупреждения памяти?

В чем смысл такого дизайнерского решения? Считается ли влияние на использование памяти слишком незначительным, чтобы его беспокоить? Это действительно мало для приложения, которое везде использует настраиваемые кнопки/заголовки панели навигации?

Легко явно связать некоторые свойства navigationItem с жизненным циклом представления контроллера — например, установить titleView в -viewDidLoad и удалить его в -viewDidUnload (self.navigationItem.titleView = nil). Но документация по свойству navigationItem предлагает избегать этого шаблона. Есть ли другие потенциальные проблемы, кроме данного примера с кнопкой «Назад»?


person Max O    schedule 20.05.2012    source источник


Ответы (1)


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

В случае, если пользовательские навигационные элементы настолько тяжелы, что вам нужно выпустить их, когда это возможно, я бы оставил реализацию по умолчанию, добавил пользовательскую категорию навигационных элементов и управлял этими элементами вручную, как я хочу (опять же путем переопределения требуемых методов UINavigationController, таких как nav -контроллеры didReceiveMemoryWarning, pushViewController:animated:, popViewControllerAnimated:animated:). Однако я не могу себе представить такого случая, когда это действительно необходимо.

фрагмент 1

@interface UIViewController (UINavigationControllerItem)

@property(nonatomic,readonly,retain) UINavigationItem *navigationItem; // Created on-demand so that a view controller may customize its navigation appearance.
@property(nonatomic) BOOL hidesBottomBarWhenPushed; // If YES, then when this view controller is pushed into a controller hierarchy with a bottom bar (like a tab bar), the bottom bar will slide out. Default is NO.
@property(nonatomic,readonly,retain) UINavigationController *navigationController; // If this view controller has been pushed onto a navigation controller, return it.

@end

фрагмент 2

@implementation UINavigationItem (Logs)


- (id)init
{
    NSLog(@"I'm initialized (%@)", [self description]);
    self = [super init];
    return self;
}

-(void) release
{
    NSLog(@"I'm released [%d](%@)", [self retainCount], [self description]);
    [super release];
}

-(void) dealloc
{
    NSLog(@"I'm deallocated [%d](%@)", [self retainCount], [self description]);
    [super dealloc];
}

@end
person A-Live    schedule 21.05.2012
comment
Отслеживание количества сохранений бесполезно. Просто отследите Dealloc. - person bbum; 21.05.2012
comment
@bbum меня впечатлило большое количество звонков о выпуске, не уверен, что кому-то это интересно, но неважно. Вызов Release с keepCount 1 должен быть в порядке, так как журнал помещается перед [super release]. Я не знаю, будет ли Dealloc must называться immediately после такого релиза, но для меня это довольно близко к Dealloc. - person A-Live; 21.05.2012
comment
Я думаю, вы неправильно поняли; результат, возвращаемый из retainCount, не имеет смысла, как в этом контексте, так и вообще, а переопределение release не показывает ничего особенно интересного. Хотя вы можете установить здесь точку останова, гораздо лучше использовать инструмент Allocations для отслеживания всех событий сохранения/освобождения. - person bbum; 21.05.2012
comment
@bbum я не могу согласиться с тем, что retainCount бессмысленно, и я серьезно сомневаюсь, что установка точки останова при выпуске лучше, чем записывать ее. У меня также было много проблем с использованием инструментов, поэтому я предпочитаю использовать стабильное решение, которое также дает нам возможность для специального тестирования. Ваше здоровье. - person A-Live; 21.05.2012
comment
Нет ничего, что может сообщить вам continueCount, что нельзя было бы найти с помощью других средств. Это в сочетании с тем, насколько сильно он вводит в заблуждение (см. whentouseretaincount.com), делает его бесполезным. Я не имел в виду, что установка точки останова при выпуске была альтернативой, но отладка путем регистрации, скажем, выпуска без контекста обратной трассировки также практически бесполезна. Вы можете добиться успеха с помощью этих шаблонов, но это не значит, что нет гораздо лучших способов сделать это. - person bbum; 22.05.2012
comment
@bbum Посмотрел ссылку, ваша озабоченность ясна, я буду очень признателен, если вы снова прочитаете пример... Вы бы подумали об этом разделе и поняли, что не все так думают, у некоторых программистов есть хорошая алгоритмическая понимание :) Некоторые не могут найти ничего вводящего в заблуждение в упомянутом здесь retainCount поведении. Давайте будем честными, это всего лишь пугающая детская сказка, а не профессиональный манифест. Что касается журнала - это один из других инструментов, который мы используем для удобства (эй, я не говорю, что NSLog следует использовать для сбора трассировки, но улучшенная версия может быть очень мощной). - person A-Live; 22.05.2012
comment
Это очень профессиональный манифест; единственная причина, по которой функция continueCount не устарела и не удалена, связана с проблемами совместимости с устаревшими версиями. На самом деле, в ARC оно удалено именно потому, что ARC удалось обойти это ограничение. Если вы понимаете алгоритмы, лежащие в основе retainCount — что они никогда не отражают автовыпуск, бесполезны перед лицом потоков и часто кажутся случайными для классов, предоставляемых фреймворком — вы бы знали, что они бесполезны для отладки (особенно в свете доступно много лучших инструментов). - person bbum; 22.05.2012
comment
@bbum Нет, я до сих пор не могу понять, в чем проблема с таким поведением. Одно и то же свойство, исчезающее в каждом ожидающем авторелизе, разбитое на потоки и отражающее только созданные пользователем права собственности (так в оригинале), было бы бесполезным кусочком радуги, в то время как со всеми упомянутыми вами вещами все в порядке. Это о знании слабых мест и легком их рассмотрении. Насколько я знаю, retainCount не устарела, не удалена, нет необходимости переключаться на ARC в ближней функции, я также не знаю о каких-либо проблемах совместимости, кроме низкого уровня знаний новичков. - person A-Live; 22.05.2012
comment
@A-Live - Совет: вы можете проверить, где он работает и к каким проектам он приложил руку, прежде чем продолжать этот спор. Ты не выиграешь это. Кроме того, вам, вероятно, следует прочитать его эпический разбор -retainCount, который, надеюсь, прояснит ситуацию: friday.com/bbum/2011/12/18/retaincount-is-useless - person Brad Larson; 22.05.2012
comment
@Brad Larson @bbum Статья великолепна в качестве описания, и мне особенно нравится заключительный раздел Итак, когда остается полезной функция continueCount. Однако, не могли бы вы на несколько минут вернуться на землю и взглянуть на вопрос оттуда? У вас есть 8 разъяснений, это здорово. Почему вы пытаетесь убедить нас забыть retainCount вместо того, чтобы понять концепцию и использовать ее надлежащим образом? Это для меня неразгаданная загадка, возможно, общаясь с менее опытной толпой, ты должен делать это ради других, тогда спасибо. - person A-Live; 22.05.2012