PrepareForSegue не вызывается после performSegue: withIdentifier: с popover style
У меня есть универсальное приложение, где я использую один и тот же контроллер для раскадровки IPad и IPhone.
Я положил UILongPressGestureRecognizer на UITableView, что, когда ячейка нажата на iPhone, она вызывает действие, выполняющее segue:
-(IBAction)showDetail:(id)sender {
UILongPressGestureRecognizer *gesture = (UILongPressGestureRecognizer*)sender;
if (gesture.state == UIGestureRecognizerStateBegan) {
CGPoint p = [gesture locationInView:self.theTableView];
NSIndexPath *indexPath = [self.theTableView indexPathForRowAtPoint:p];
if (indexPath != nil) {
[self performSegueWithIdentifier:SEGUE_DETAIL sender:indexPath];
}
}
}
segue представляет собой подробное представление, выполненное как "push". Первое, что вы должны заметить, это то, что отправитель является NSIndexPath, это единственный способ, которым я нашел для передачи выбранной ячейки. Может быть, есть лучшее решение.
Все работает отлично, в некотором смысле, что выполняется segue, и до того, как будет вызвана команда prepareForSegue.
Однако бывает, что на iPad я изменил идентификатор segue на Popover.
Теперь все работает частично, выполняется segue, но prepareForSegue не вызывается, поэтому контроллер представления назначения не настроен, как и должно быть.
Что я делаю неправильно?
Ответы
Ответ 1
То, что я обнаружил до сих пор, заключается в том, что с любым идентификатором segue, который не является popover, это invocations, сделанные iOS:
- prepareForSegue (на контроллере источника)
- viewDidLoad (на контроллере назначения)
в то время как в popover segue порядок вызова:
- viewDidLoad (на контроллере назначения)
- prepareForSegue (на контроллере источника)
только потому, что я поместил всю свою логику в viewDidLoad, контроллер не был правильно инициализирован, и произошел сбой. Так что это не совсем так, что prepareForSegue не вызывается, правда в том, что я получаю исключение, и я ошибочно ошибаюсь, поскольку prepareForSegue не получает вызов.
Я не мог поместить все в viewWillAppear, потому что должен был быть вызван вызов CoreData, и я не хотел проверять, поддерживаются ли сущности каждый раз при отображении представления.
Как я решил это? Я создал другой метод в контроллере назначения
-(void)prepareViewController {
// initialization logic...
}
и изменение метода prepareForSegue в самом исходном контроллере:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
MyViewController *mvc = (MyViewController*)[segue destinationViewController];
// passing variable
// with segue style other than popover this called first than viewDidLoad
[email protected]"prop1";
[email protected]"prop2";
// viewWillAppear is not yet called
// so by sending message to controller
// the view is initialized
[mvc prepareViewController];
}
Не знаю, будет ли это ожидаемое поведение с popover, так или иначе, теперь все работает.
Ответ 2
Я заметил, что код плиты котла для шаблона Master-Detail Xcode (iPhone) использует следующий шаблон для настройки подробного просмотра VC:
- подробные настройки VC (для свойств) перезаписываются для вызова метода configureView (configureView будет обновлять все ваши элементы управления в представлении, например, метки и т.д.).
- Подробный метод VC viewDidLoad также вызывает метод configureView
Я не последовал этому шаблону на днях, когда пытался переустановить подробный VC в своем приложении для фильма, и это вызвало у меня проблемы.
У меня нет большого опыта с popovers; однако, если вышеприведенный шаблон используется с детальным VC, который отображается внутри popover, то не будет ли конфигурация детализации VC настроена при настройке подробных свойств VC из метода prepareForSegue?