Сохранить/освободить шаблон для UIPopoverController, UIActionSheet и контроллеров модального представления?

Мне несколько неясны шаблоны владения объектами, необходимые для следующих случаев. Когда мой UIViewController представляет всплывающий контроллер, лист действий или другой контроллер представления как модальный, должен ли я держать сохраненную ссылку на этот дочерний контроллер, пока он не будет отклонен?

Другими словами, следующие строки кода эффективно «передают» право собственности или нет?

[aPopoverController presentPopoverFromBarButtonItem:someButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];

[anActionSheet showFromBarButtonItem:someButtonItem animated:NO];

[aViewController presentModalViewController:someOtherViewController animated:YES];

Может ли кто-нибудь указать мне на явную документацию по этому вопросу?


person Ben Zotto    schedule 19.05.2010    source источник


Ответы (2)


UIPopoverViewController имеет немного другое управление/владение памятью. Present popover не сохраняет память, поэтому вы не можете передать право собственности на свой контроллер popview на представляющий объект.

Чтобы избежать утечки памяти, вы должны принять UIPopoverControllerDelegate и реализовать метод DidDismissPopOver следующим образом:

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
    [popoverController release];
}

Таким образом, вы можете безопасно выделить и представить PopOver:

-(void)showSearch:(id)sender {
    SearchViewController *searchVC = [[SearchViewController alloc] init];
    UIPopoverController *popVC = [[UIPopoverController alloc] initWithContentViewController:searchVC];
    popVC.delegate = self;
    [popVC setPopoverContentSize:CGSizeMake(320, 100)];
    [popVC presentPopoverFromRect:CGRectMake(200, 200, 320, 100) inView:self.view permittedArrowDirections:0 animated:YES];
    [searchVC release];
}
person valvoline    schedule 17.11.2010
comment
Остерегайтесь, если вы сделаете это таким образом, searchVC будет просачиваться. Добавьте автовыпуск. - person steipete; 15.04.2011
comment
Да, searchVC просочился. Вместо авторелиза подойдет и простой релиз. Добавьте это в последнюю строку: [searchVC release]; - person Jason Moore; 19.04.2011
comment
Как сказано в документации для popoverControllerDidDismissPopover:: Контроллер всплывающих окон не вызывает этот метод в ответ на программные вызовы метода rejectPopoverAnimated:. Если вы отклоняете всплывающее окно программно, вам следует выполнять любые действия по очистке сразу после вызова метода rejectPopoverAnimated:.. Поэтому, если вы используете dismissPopoverAnimated:, вам также нужно будет вызвать релиз после него, иначе вы получите утечку. - person ivanzoid; 31.05.2011
comment
Принятие этого ответа наконец. Спасибо всем за вклад. Неприятно, что этот элемент управления ведет себя иначе, чем те, у которых номинально похожие модели взаимодействия. - person Ben Zotto; 24.08.2011

Представление контроллера модального представления сохраняет UIViewController. Это на самом деле не ясно из документов. Однако я протестировал его, используя следующий код...

NSLog(@"BEFORE %d", [self.setupViewController retainCount]);
[self.navigationController presentModalViewController:self.setupViewController animated:YES];
NSLog(@"AFTER %d", [self.setupViewController retainCount]);

self.setupViewController уже сохранен локально, но при его представлении выводится следующее:

2010-05-19 10:07:36.687 LocateMe[27716:207] BEFORE 1
2010-05-19 10:07:36.762 LocateMe[27716:207] AFTER 3

Поэтому он, вероятно, сохраняется в локальном свойстве modalViewController, а также в иерархии представлений. Отказ от этого уравновесит их.

Итак, суть в том, что сохраните его, если вы хотите управлять им напрямую, но вам это не обязательно.

РЕДАКТИРОВАТЬ. Чтобы было ясно, правильный шаблон должен всегда сохранять объект, если вы устанавливаете себя в качестве его делегата. Это потому, что вы должны установить для делегата значение nil в файле Dealloc для безопасности. Однако на практике модальный контроллер всегда будет уволен до того, как вы освободите его, так что это не проблема. Вы заметите, что Apple также нарушает это правило в [UIView setAnimationDelegate:], который фактически сохраняет установленный вами делегат.

person DougW    schedule 19.05.2010
comment
Я бы также добавил, что большая часть примера кода Apple инициализирует UIViewController, представляет его модально, а затем выпускает. Посмотрите пример AddMusic. - person DougW; 19.05.2010
comment
То же самое относится к всплывающим окнам и листам действий? - person Ben Zotto; 01.06.2010
comment
Да, вы можете запустить UIAlertView, а затем выпустить его. Или вы можете сохранить его, если хотите что-то с ним сделать. В любом случае все в порядке, просто убедитесь, что вы сбалансировали сохранение/релизы. - person DougW; 01.06.2010
comment
Это неправильно - если вы выделили всплывающее окно с автоматическим выпуском и представили его, вы выйдете из строя, потому что оно освобождается после представления. Это означает, что вы должны удерживать ссылку на всплывающее окно до тех пор, пока оно не будет отклонено, если только вы не согласны с его утечкой. Это кажется совершенно хромым и несовместимым с другими вещами, но вот оно. - person Ben Zotto; 27.06.2010
comment
Это правильно, и представление предупреждений НЕ протекает. Прочтите документацию (bit.ly/b25V5U). Apple постоянно демонстрирует шаблон alloc-present-release как для модальных окон, так и для представлений предупреждений. - person DougW; 29.06.2010
comment
@DougW - Используется ли шаблон alloc-present-release и для UIPopoverController? - person Florin; 27.07.2010
comment
@Florin - я не вижу примера Apple, но уверен, что это то же самое. Поскольку вы установили для него делегата, правильный шаблон должен состоять в том, чтобы сохранить его, а затем установить для этого делегата значение nil в вашем Dealloc, чтобы быть в безопасности. Технически это правильный способ сделать что-то, но поскольку он автоматически умирает, когда это делает ваш контроллер представления, это, вероятно, не является строго необходимым. - person DougW; 27.07.2010