如何使用在自适应故事板中关闭iPhone弹出窗口

时间:2014-09-16 04:39:54

标签: ios8 uistoryboard uistoryboardsegue

我是iOS开发的新手,我正在尝试同时学习故事板,Swift和iOS 8的新功能。

我创建了一个非常简单的故事板,它使用Popover演示文件segue来显示另一个视图。在模拟器上,如果我为iPad运行它,它按预期工作。但是,如果我为iPhone而不是弹出窗口运行它,它会在原始视图的顶部显示全屏视图。这可以;但是,没有办法解雇它并回到原来的屏幕。

我观看了WWDC 2014视频“228 A Look inside presentation controllers”,如果他们完全使用代码构建用户界面,他们可以显示一个关闭按钮。

我还看过“411界面构建器中的新功能”会话,他们说这可以在Interface Builder中完成,但他们没有显示它,承诺在实验室中展示如何做到这一点,如果有人有兴趣。不幸的是,我没有参加WWDC 2014,或者认识任何人。我的Google搜索也没有返回任何有用的内容。

5 个答案:

答案 0 :(得分:12)

您可以像这样添加导航控制器 -

  • 将弹出视图控制器设置为根视图控制器到导航控制器。
  • 删除您当前正在使用的popover segue
  • 将segue从显示弹出窗口的按钮重新连接到导航控制器。 在iPad上你会得到一个popover,在iPhone上你会得到一个模态演示。 iPad和iPhone都会显示导航控制器。根据您的使用情况,这可能是您想要的,也可能不是。这是一个关于故事板应该是什么样子的屏幕显示。
    • Your storyboard should look like this if you add the navigation controller in storyboard.

如果你真的希望你的视图控制器永远是一个弹出窗口,请按原样保留你的故事板,并将这样的内容添加到你的视图控制器中,以显示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;
   }
}

呈现弹出窗口的视图控制器还需要响应此UIPopoverPresentationDelegate方法

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

最后,您可以执行以下操作,仅将导航控制器添加到iPhone上视图控制器的模式演示文稿中,并将弹出窗口保留在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;
}

祝你好运!

答案 1 :(得分:10)

如果您想要的是iPad上的弹出窗口,但是iPhone上有关闭按钮的模态表,那么您可以在故事板中为弹出框创建额外的导航控制器。

在Xcode 6.3故事板中,您只需连接一个视图控制器并将segue指定为“作为弹出窗口存在”

下面的代码应该放在视图控制器中,该控制器会切换到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)
}

答案 2 :(得分:3)

我不确定为什么你需要为Done按钮设置故事板设置,所有的工作都可以通过几行代码以编程方式完成。重要的是实现一些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)
}

你完成了!

答案 3 :(得分:1)

在我的情况下,我有一个小弹出窗口,我想在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
    }
}

答案 4 :(得分:0)

使用mimimal代码可以实现它,同时将逻辑放入故事板。在呈现弹出框的视图控制器中,只需放入标记方法

@IBAction func unwindToContainerVC(segue: UIStoryboardSegue) {

}

它不需要任何代码但需要存在,因此您可以在以后使用界面构建器时控制拖动到“退出”图标。

我的popover内容不占用整个背景视图,但周围的边距很小。这意味着您可以使用界面构建器为此视图创建轻击手势识别器。控制将手势识别器拖动到Exit图标,然后弹出一些Exit选项,其中一个是unwindToContainerVC方法,如上所示。

现在任何边缘的点击(例如在iPhone 4S场景中)都会将您带回到呈现视图控制器。

以下是手势识别器的连接检查器: enter image description here