Является ли parentViewController всегда контроллером навигации? - PullRequest
7 голосов
/ 28 октября 2008

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

Я делаю приложение, управляемое UINavigationController. В AppDelegate я создаю экземпляр этого класса, используя «страницу 1» в качестве контроллера корневого представления.

UINavigationController *aNavigationController = [[UINavigationController alloc] 
     initWithRootViewController:page1ViewController];

Теперь вот где у меня проблема. На «странице 1» я хотел бы использовать модальный контроллер представления, который скользит по интерфейсу и затем исчезает, когда пользователь сделал редактирование. Я делаю это, используя такой код внутри Page1ViewController:

[self presentModalViewController:myModalViewController animated:YES];

Когда отсутствует контроллер модального вида, я хочу, чтобы значение на «странице 1» изменялось в зависимости от того, что пользователь ввел в контроллер модального вида. Итак, я написал такой код, который находится в Modal View Controller:

[self.parentViewController dismissModalViewControllerAnimated:YES];
[self.parentViewController doSomethingPleaseWithSomeData:someData];

Обновление страницы 1 не происходило, и мне потребовалось много времени, чтобы понять, что сообщение «doSomethingPleaseWithSomeData» отправляется не в Page1ViewController, а в Navigation Controller.

Всегда ли этого следует ожидать при использовании контроллеров навигации? Возможно, я что-то неправильно настроил? Есть ли простой способ получить в View Controller, который я хочу (в данном случае, Page1ViewController).

Ответы [ 4 ]

14 голосов
/ 11 ноября 2008

Я бы рекомендовал использовать шаблон делегирования для решения вашей проблемы. Создать недвижимость

@property (nonatomic, assign) id <MyModalViewDelegate> delegate;

и соответствующий протокол

@protocol MyModalViewDelegate
@optional
    - (void)myModalViewControllerDidFinish:(MyModalViewController *)aModalViewController;
@end

Когда пользователь завершает просмотр (например, нажимает кнопку сохранения), отправьте это сообщение:

if ([self.delegate respondsToSelector:@selector(myModalViewControllerDidFinish:)])
    [self.delegate myModalViewControllerDidFinish:self];

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

Так Apple решает эту проблему, например, в UIImagePickerController и UIPersonPickerController.

4 голосов
/ 28 октября 2008

Есть несколько способов справиться с этим. Самое простое, вероятно, это просто добавить свойство UIViewController в myModalViewController и установить его в page1Controller перед его представлением:

myModalViewController.logicalParent = self; //page1Controller
[self presentModalViewController:myModalViewController animated:YES];

Просто убедитесь, что вы добавили соответствующую переменную экземпляра @property и @synthesize для logicParent в myModalViewController, тогда у вас будет возможность передавать данные обратно в ViewController, который запускает модальное диалоговое окно. Это также для передачи данных назад и вперед между различными уровнями навигации, прежде чем вы помещаете их в стек.

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

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

Просто столкнулся с той же проблемой. Я считаю, что это ошибка. Мой сценарий следующий: Иерархия навигации с A, B и C отображает контроллеры в этом порядке. На C есть кнопка, которая открывает модальный контроллер представления под названием D. Как только D представлен, навигационный контроллер удаляет C из своей иерархии, что является ужасным поведением. Как только D отклоняется, контроллер навигации создает новый контроллер представления типа C и помещает его в свою иерархию, чтобы восстановить исходный. Грозный. Мое решение состоит в том, чтобы взломать иерархию навигации таким образом (очень плохое решение, но оно работает хорошо. С двумерным массивом вы могли бы реализовать стековые модалы):

- (void)presentModalViewController:(UIViewController *)c {
    [self.navigationHierarchy removeAllObjects];
    [self.navigationHierarchy addObjectsFromArray:[navigation viewControllers]];
    [navigation setViewControllers:[NSArray array] animated:YES];
    [navigation presentModalViewController:c animated:YES];
}

- (void)dismissModalViewController {
    [navigation dismissModalViewControllerAnimated:YES];
    [navigation setViewControllers:[NSArray arrayWithArray:self.navigationHierarchy] animated:YES];
}

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

NSMutableArray *navigationHierarchy;
UINavigationController *navigation;
1 голос
/ 24 сентября 2010

Я только что столкнулся с этой же проблемой. Определенно кажется, что если вы поместите UIViewController, встроенный в NavigationController, то, когда из этого UIViewController вы представите другой UIViewController модально, слушатель думает, что презентатор является NavigationController. Другими словами, parentViewController является неправильным.

Бьюсь об заклад, это ошибка: либо это, либо документация кажется неполной. Я буду спрашивать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...