Подтвердить что ты не робот

Как отклонить модальный код, который был представлен в UIStoryboard с модальным отступлением?

Настройка: у меня установлена ​​раскадровка с двумя простыми контроллерами вида A и B. В A есть кнопка, которая переходит в B с модальным сегментом. B представлен модальный переход сверху A. Его тонкий.

Вопрос: есть ли способ выскочить B и вернуться к A с помощью некоторой простой магии раскадровки?

Обратите внимание, что если все это было в контроллере навигации, и я использовал push-сег, он неявно должен был быть рассмотрен навигационным контроллером. Будет кнопка "назад". Theres ничего сопоставимого для модалов, мне нужно создать UI сам, что хорошо, но мне интересно, есть ли механик segue, который я могу использовать для сигнала, чтобы вернуться с B на A.

Теперь метод oldskool для построения возврата из B в будет:

  • создать свойство делегата в B
  • set A является делегатом B, когда воспроизводится модальный переход segue (я могу подключиться к этому с помощью метода prepareForSegue: sender: in As)
  • когда его время отклоняется, сигналы B передаются его делегату
  • A реализует метод делегата, который отклоняет B

Это работает, но чувствует себя слишком много накладных и глупых.

Есть ли какой-то механик UIStoryboard, который я пропустил, что в основном будет делать "обратный модальный сегмент"?

4b9b3361

Ответ 1

Нет никакой магии раскадровки для отклонения модального контроллера представления, не записывая хотя бы немного кода.

Но пока вам нужно реализовать какой-то собственный код, вам необязательно идти на эти проблемы. Вы можете просто нажать кнопку в контроллере B, который вызывает [self dismissViewControllerAnimated:YES completion:nil]. (Документы говорят, что диспетчер представления представления должен быть уволен, но они также говорят, что сообщение будет перенаправлено контроллеру представления представления, если он вызывается присутствующим. Если вы хотите быть более откровенным в этом вопросе, в некоторых случаях, например, когда один контроллер модального представления представлен от другого - вы можете явно ссылаться на презентатора с помощью self.presentingViewController и вызывать dismiss... оттуда.)

Вы видите делегирование бизнеса в некоторых приложениях, потому что это один из способов уведомления контроллера вида A о том, что сделал пользователь во время просмотра контроллера B... но это не единственный способ. Там KVO, уведомления или просто вызов методов A после ссылки на него с помощью self.presentingViewController (предполагая, что B всегда знает, что он представлен A). И если A не нужно знать о том, что произошло в B (скажем, потому что пользователь нажал кнопку "Отмена" ), нет необходимости делать что-либо из этого - вы можете просто отказаться от модальности и сделать с ним.


В iOS 6 и более поздних версиях unind segues добавляет еще один вариант, предоставляя немного "магии раскадровки" для отклонения контроллеров модального представления (или иначе "отступающих" от последовательности segues). Но этот подход по-прежнему требует некоторого кода - вы не можете установить его полностью в раскадровке. Однако с положительной стороны этот код предоставляет путь для получения информации от диспетчера представлений, который отклоняется (B), к тому, который представил его (A).

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

  • Определите метод IBAction в классе контроллера вида, который хотите развернуть, - тот, который представляет собой контроллер модального представления, а не сам контроллер модального представления (контроллер просмотра A в вашем вопросе). В отличие от обычных методов IBAction, они должны принимать параметр типа UIStoryboardSegue *; например.

    - (IBAction)unwindToMainMenu:(UIStoryboardSegue*)sender
    
  • В представленном контроллере представления (B в вопросе) проведите элемент управления к зеленому значку выхода и выберите метод, который вы определили.

  • В вашей реализации метода разматывания вы можете обратиться к segue sourceViewController, чтобы получить информацию с отклонения диспетчера представлений. Вам не нужно вызывать dismissViewControllerAnimated:completion:, потому что segue обрабатывает отклонение контроллера вида, который уходит.

Ответ 2

Там есть маска раскадровки для достижения этой цели. Он известен как развязка. В файле .h вы реализуете всевозможные методы стиля "целевого действия", которые вам нужны, но сколько раз вам нужно. Для модального, обычно два (отменить и сохранить). Поэтому в моем файле A.h я бы добавил:

// A.h file
- (IBAction)myCancelUnwindSegueCallback:(UIStoryboardSegue *)segue;
- (IBAction)mySaveUnwindSegueCallback:(UIStoryboardSegue *)segue;

Теперь, в вашем раскадровке, если у вас есть segue от A до B. Теперь вы можете выполнить перетаскивание стиля стиля "целевое действие" с кнопок отмены/сохранения в B до зеленого значка "Выход" в нижней части контроллер B в вашем раскадровке. Когда вы это сделаете, Xcode подберет два метода, которые мы создали (поскольку они находятся в файле заголовка A, и они имеют правильную подпись (например, IBAction и UIStoryboardSegue *.), А B - это место назначения из A) Итак, там у вас это есть. У вас есть волшебство раскадровки, которое вы искали!

В реализации двух обратных вызовов у вас будет что-то вроде:

// A.m file
- (IBAction)myCancelUnwindSegueCallback:(UIStoryboardSegue *)segue {
    UIViewController *modalGoingAway = segue.sourceViewController;
    // Do something (like get data) from modalGoingAway if you need to...
}

- (IBAction)mySaveUnwindSegueCallback:(UIStoryboardSegue *)segue {
    UIViewController *modalGoingAway = segue.sourceViewController;
    // Do something (like get data) from modalGoingAway if you need to...
}

Наконец, если этот подход удовлетворит ваши потребности, отлично. Все готово. Тем не менее, я все еще подключаю весь шаблон делегирования протокола /dataSource, если "on cancel" или "on save". Я хочу выполнить некоторые операции с частными свойствами B, прежде чем передавать управление A, чтобы удалить B из иерархии представлений.