Как использовать отклонение iPhone в Adaptive Storyboard

Я новичок в разработке iOS, и одновременно пытаюсь изучить раскадровку, Swift и новые функции iOS 8.

Я создал очень простую раскадровку, которая использует презентацию Popover segue для отображения другого представления. На симуляторе, если я запустил это для iPad, он работает так, как ожидалось. Однако, если я запустил его для iPhone, вместо popover, он отобразит полноэкранный режим, поверх исходного. Это отлично; однако, нет способа отклонить его и вернуться к исходному экрану.

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

Я также смотрел сеанс "411 What new in interface builder", где они говорят, что это можно сделать в Interface Builder, но они не показывают его, обещая показать, как это сделать в лаборатории, если кто-либо заинтересован. К сожалению, я не посещал WWDC 2014, или знаю всех, кто имеет. Мои поисковые запросы Google не возвратили ничего полезного.

Ответ 1

Вы можете добавить контроллер навигации следующим образом:

  • Установите контроллер popover view в качестве контроллера корневого представления на контроллер навигации.
  • Удалить сегмент popper, который вы используете в настоящее время
  • Подключите сегмент с кнопки, с которой вы показываете popover от навигационного контроллера. На iPad вы получите popover и на iPhone вы получите модальную презентацию. И iPad, и iPhone покажут навигационный контроллер. В зависимости от вашего варианта использования это может быть или не быть чем-то, что вы хотите. Здесь показано, как выглядит раскадровка.
    • Your storyboard should look like this if you add the navigation controller in storyboard.

Если вы действительно хотите, чтобы ваш контроллер просмотра всегда был popover, оставите свою раскадровку так, как есть, и добавьте что-то подобное этому контроллеру вида, который представляет popover-

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"Your segue name"]) {
    UIViewController *yourViewController =  segue.destinationViewController;
    yourViewController.modalPresentationStyle = UIModalPresentationPopover;
    UIPopoverPresentationController *popoverPresentationController = yourViewController.popoverPresentationController;
    popoverPresentationController.delegate = self;
   }
}

Контроллер представления, представляющий popover, также должен ответить на этот UIPopoverPresentationDelegate метод

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller 
{
return UIModalPresentationNone;//always popover.
}

Наконец, вы можете сделать следующее, чтобы добавить контроллер навигации в модульную презентацию вашего контроллера представлений на iPhone и оставить popover на iPad без контроллера навигации.

  • Оставьте свою раскадровку как есть.
  • Правильное место для ввода контроллера навигации находится в - (UIViewController *)presentationController:(UIPresentationController *)controller viewControllerForAdaptivePresentationStyle:(UIModalPresentationStyle)style. Чтобы это было вызвано, мы должны указать себя как делегат UIPopoverPresentationController. Еще раз мы сделаем это в prepareForSegue:

    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
    if ([segue.identifier isEqualToString:@"Your segue name"]) {
        UIViewController *yourViewController =  segue.destinationViewController;
        yourViewController.modalPresentationStyle = UIModalPresentationPopover;
        UIPopoverPresentationController *popoverPresentationController = yourViewController.popoverPresentationController;
        popoverPresentationController.delegate = self;
        }
    }
    

Затем мы сделаем это в методе делегата, о котором я упоминал выше

-(UIViewController *)presentationController:(UIPresentationController *)controller viewControllerForAdaptivePresentationStyle:(UIModalPresentationStyle)style
{
    UIViewController *presentedViewController = controller.presentedViewController;
    UINavigationController *navigationController = [[UINavigationController alloc]
                 initWithRootViewController:presentedViewController];
    UIBarButtonItem *dismissButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonItemStyleDone target:self action:@selector(done:)];
    presentedViewController.navigationItem.rightBarButtonItem = dismissButton;

    return navigationController;
}

Удачи!

Ответ 2

Если то, что вы хотите, - это popover на вашем iPad, но модальный лист с закрытой кнопкой на вашем iPhone, тогда вы можете сделать это, не создавая дополнительный контроллер навигации в раскадровке для popover.

В раскадровке Xcode 6.3 вы просто подключаете контроллер вида и обозначаете segue как "Present as Popover"

Код, приведенный ниже, должен находиться в контроллере представления, который переместится в popover, а не в самом popover:

Сначала вы настроили делегат popover:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if (segue.identifier == "myPopoverSegueName") {
        let vc = segue.destinationViewController
        vc.popoverPresentationController?.delegate = self
        return
    }
}

Затем вы добавите расширение делегата (ниже кода вашего контроллера) и создайте кнопку навигации/закрытия на лету:

extension myViewController: UIPopoverPresentationControllerDelegate {

    func presentationController(controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
        let btnDone = UIBarButtonItem(title: "Done", style: .Done, target: self, action: "dismiss")
        let nav = UINavigationController(rootViewController: controller.presentedViewController)
        nav.topViewController.navigationItem.leftBarButtonItem = btnDone
        return nav
    }

}

Затем вы добавляете функцию увольнения, и вам должно быть хорошо:

func dismiss() {
    self.dismissViewControllerAnimated(true, completion: nil)
}

Ответ 3

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

 func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle
 {
       return .FullScreen
 }
 func presentationController(controller: UIPresentationController,
        viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController?{

      var navController:UINavigationController = UINavigationController(rootViewController: controller.presentedViewController)
      controller.presentedViewController.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action:"done")
      return navController       
}

Затем, простой способ реализовать поведение отклонения для popover в случае, если он был представлен в полноэкранном режиме:

func done (){        
      presentedViewController?.dismissViewControllerAnimated(true, completion: nil)
}

и вы сделали!

Ответ 4

Его можно сделать с кодовым кодом, а вместо этого ввести логику в раскадровку. В контроллере представления, который представляет popover, просто введите маркерный метод

@IBAction func unwindToContainerVC(segue: UIStoryboardSegue) {

}

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

У меня есть мой popover-контент, который не занимает весь фоновый вид, но имеет небольшой запас вокруг него. Это означает, что вы можете использовать построитель интерфейса для создания распознавателя жестов для этого представления. Control перетащите распознаватель жестов на значок "Выход", который затем отображает некоторые варианты выхода, одним из которых является метод unwindToContainerVC, как показано выше.

Теперь любой щелчок по краю (например, в сценарии iPhone 4S) возвращает вас к контроллеру представления.

Вот инспектор соединений для распознавателя жестов: введите описание изображения здесь

Ответ 5

В моем случае у меня появилось небольшое всплывающее окно, которое я хотел всплывать как на iPhone, так и на iPad - и мне не хотелось использовать панель навигации с Dismiss. Обнаружено, что нужно реализовать два вызова делегата (Swift 3.0):

extension MyViewController : UIPopoverPresentationControllerDelegate {
    // Needed for iPhone popup
    func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
        return .none
    }

    // Needed for iPhone in landscape
    func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
        return .none
    }
}