Сохраняет ли UIViewController presentModalViewController: animated: модальный контроллер? - PullRequest
11 голосов
/ 18 декабря 2010

Это влияет на то, как я взаимодействую с моими модальными контроллерами.Когда я только начинал разработку для iOS, я предполагал, что UIViewController не не сохранит модально представленный вид.Ну, на самом деле это было больше похоже на то, что у меня не было никаких оснований предполагать, что действительно * сохранило их.Это оставило мне довольно неловкие попытки освободить их, когда я знал, что они закончили бы анимацию увольнения:

_myViewController = [[UIViewController alloc] init];
[self. present modalViewController:_myViewController animated:YES];
/* 
Some stuff, then in a different method all together,
probably as the result of a delegate callback or something...
*/
[self dismissModalViewControllerAnimiated:YES];
[_myViewController performSelector:@selector(release) withObject:nil afterDelay:0.5f];

Затем я увидел свойство modalViewController UIViewController и подумал: «Человек, янадеюсь, что это свойство сохранится, когда будет представлен модальный контроллер представления. "Конечно же, я зарегистрировал счет сохранения для нескольких из этих попыток и заметил общее увеличение сразу после вызова на presentModalViewController:animated: (я знаю, счет сохранения не является идеальным показателем).Итак, где-то вдоль линии, я начал использовать гораздо более приятный шаблон, в котором я предполагаю, что любой объект контроллера, который я представляю модально, сохраняется представителем контроллера.Это позволяет мне написать стандартный код:

UIViewController* myViewController = [[UIViewController alloc] init];
[self presentModalViewController:myViewController animated:YES];
[myViewController release]; // <- Fire and forget!

Теперь, конечно, неловкости нет: не нужно ждать окончания анимации или даже сохранять ссылку на представленный контроллер, если я неэто не нужноЯ могу слепо отклонить это позже и не беспокоиться о утечке.Мне это нравится.

Я зарегистрировал множество dealloc в моих модально представленных контроллерах, и они всегда вызывались именно тогда, когда я хочу, что заставляет меня чувствовать себя уверенно в моем подходе: UIViewController s presentModalViewController:animated: сохраняетпредставленный контроллер как свойство modalViewController.

Но, и это суть этого вопроса, я понял, что не могу подтвердить это как задокументировано поведение.И если это не задокументировано, я не должен чувствовать себя в такой же безопасности, как и я, потому что Apple не дает никаких обещаний относительно долговечности недокументированного поведения.Свойство modalViewController является общедоступным readonly, поэтому я могу только предположить сохранение за кулисами, а в документации по presentModalViewController:animated: сказано только:

Устанавливает свойство modalViewController для указанного контроллера представления.

«Наборы» могут быть assign или retain.Ничто из того, что я читаю, не подтверждает и не отрицает мою позицию.Поскольку я часто делаю такое предположение, мне бы очень понравилось, если бы кто-то мог указать на тот факт, что я пропустил где-то в недрах документации, чтобы успокоить свой разум относительно легитимности этой практики.

РЕДАКТИРОВАТЬ: В приливе и отливе из повседневной жизни в iOS SDK, я оказался в заголовке для UIViewController и начал читать некоторые из них.Я собрал некоторую полезную информацию, которая напомнила мне об этом вопросе, и я решил опубликовать ее, если какой-то будущий пользователь наткнется на этот вопрос и захочет как можно больше информации, чтобы удовлетворить свою паранойю очень стандартной практики.Небольшой кусочек просто из блока @interface ivar в UIViewController.h:

UIViewController *_childModalViewController;

В отличие от этих других объявлений:

UIViewController *_parentViewController; // Nonretained
NSHashTable      *_childViewControllers; // Nonretained

В комментариях явно указывается, что не сохраняется.Из-за отсутствия комментариев к объявлению ivar контроллера модального представления может показаться, что является сохраненным.

Ответы [ 5 ]

14 голосов
/ 18 декабря 2010

Правила управления памятью Objective-C определяют поведение, поэтому нет необходимости явно документировать, что он сохраняет контроллер модального представления.Если объект должен сохранять переданный объект после завершения выполнения метода, он будет сохранять объект , если не указано иное .

Так что в этом случае выследует просто передать контроллер вида на presentModalViewController:animated: и затем отпустить его (или использовать авто-релиз).

Это применимо везде в Objective-C.Если объект принимает другой объект в качестве входных данных метода, вы никогда не должны сохранять этот объект от его имени.

Как и требовалось в комментариях, если вы читаете документацию Apple по управлению памятью, тогда вы найдете раздел о слабых ссылках , в котором говорится:

Важно : в Какао ссылки на источники данных таблиц,элементы представления схемы, наблюдатели уведомлений и делегаты считаются слабыми (например, объект NSTableView не сохраняет свой источник данных, а объект NSApplication не сохраняет свой делегат).Документация описывает только исключения из этого соглашения.

Это фактически говорит о том, что это соглашение само по себе и что исключения будут указаны в документации, однако, переходя к документациидля NSTableView и, глядя на метод setDataSource:, мы видим:

Обсуждение В среде управляемой памяти получатель поддерживает слабую ссылку на источник данных (чтоэто не сохраняет источник данных, см. Связь с объектами).После установки источника данных этот метод вызывает плитку.

Этот метод вызывает NSInternalInconsistencyException, если anObject не отвечает ни на numberOfRowsInTableView:, ни на tableView: objectValueForTableColumn: row:.

2 голосов
/ 18 декабря 2010

уверен, что это задокументировано. И, кстати, я не знаю другого пути: D Я использую метод alloc-present-release с тех пор, как начал программировать на iOS 1,5 года назад

Вы можете найти пример кода, если вы запустите XCode и создадите «Приложение-утилиту». В (предоставленный Apple) код должен быть:

FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:@"FlipsideView" bundle:nil];
controller.delegate = self;

controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];

[controller release];
2 голосов
/ 18 декабря 2010

Хм хороший вопрос! Я не совсем уверен в ваших предположениях. Данное свойство определяется в документах как:

@property(nonatomic, readonly) UIViewController *modalViewController

Как вы указали, в нем не указано, как оно хранится.

Этот документ: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html

фактически заявляет, что если сохранение / назначение / копирование не указано, это назначение является поведением по умолчанию.


Я также прочитал ответ d11wtq, но не уверен, что полностью согласен. Я согласен с соглашениями об управлении памятью obj-c, но во многих случаях методы каркаса не сохраняют свойства (например, слабые ссылки, делегаты и т. Д.). Я надеюсь, что кто-то может подтвердить ваши предположения.

1 голос
/ 06 февраля 2011

Я полагаю, что ответ iPortable дает вам то, что вы хотите - спокойствие, когда вы выпускаете контроллер вида таким образом.

Кстати, одна из причин, почему распечатка retainCount не являетсяХорошая стратегия отладки заключается в том, что если вы ставите NSLog или точку останова, это может быть не то место, где можно посмотреть счет сохранения.Некоторые удержания или освобождения могут следовать за ПОСЛЕ того, как вы проверите счетчик сохранений, вызванный интересующим вас событием.

Так что, если вы действительно хотите знать, каким будет счет удержания с момента события, просто переопределите - (id)отпусти и - (void) выпусти метод и распечатай там логи и посчитай сам.Конечно, вы должны вызывать retain / release суперкласса в конце ваших методов.Таким образом, например, вы можете получить очень четкий ответ на свой первоначальный вопрос.

0 голосов
/ 20 марта 2013

, если вы выполняете анимацию при представлении контроллера модального вида, например

[viewController presentViewController:modalViewController animated:YES completion:^{
    NSLog(@"presentViewController completion");
}];
/*DONT RELEASE IF THERE IS ANIMATION*/
//[modalViewController release];

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

Если вы НЕ используете анимацию , вы можете освободить его сразу после его модального представления следующим образом.

   [viewController presentViewController:modalViewController animated:NO completion:^{
    NSLog(@"presentViewController completion");
}];

[modalViewController release];/*YOU MAY RELEASE MODALVIEW CONTROLLER IMMEDIATELY*/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...