【问题标题】:How to use dismiss an iPhone popover in an Adaptive Storyboard如何在自适应故事板中使用关闭 iPhone 弹出框
【发布时间】:2014-11-09 17:33:11
【问题描述】:

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

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

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

我也看过“411 What's new in interface builder”会议,他们说这可以在 Interface Builder 中完成,但他们没有展示它,并承诺在实验室中展示如何做到这一点,如果有人的话有兴趣。不幸的是,我没有参加 WWDC 2014,也不认识任何参加过的人。我的 Google 搜索也没有返回任何有用的信息。

【问题讨论】:

  • 故事板中有 UINavigationController 吗?
  • @AdityaWirayudha:我没有,但如果需要可以添加。
  • 请尝试一下,我相信它会在导航堆栈中添加呈现视图控制器(因此呈现视图控制器上的后退按钮)
  • @AdityaWirayudha:不幸的是,它不起作用。

标签: ios8 uistoryboard uistoryboardsegue


【解决方案1】:

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

  • 将弹出视图控制器设置为导航控制器的根视图控制器。
  • 删除您当前使用的弹出框转场
  • 将显示弹出框的按钮的 segue 重新连接到导航控制器。 在 iPad 上,您将获得一个弹出框,在 iPhone 上,您将获得一个模态演示。 iPad 和 iPhone 都将显示导航控制器。根据您的用例,这可能是您想要的,也可能不是。这是故事板应该是什么样子的屏幕显示。

如果您确实希望您的视图控制器始终是一个弹出框,请保留您的情节提要,并在您的视图控制器中添加类似的内容来呈现弹出框-

-(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;
}

祝你好运!

【讨论】:

  • 在显示弹出框的情况下如何使“完成”按钮不显示?
  • - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"page size popover"]) { UINavigationController *navController = segue.destinationViewController; UIModalPresentationStyle style = navController.modalPresentationStyle; if (style == UIModalPresentationPageSheet) { UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonItemStyleDone target:self action:@selector(done:)]; [navController.navigationItem setRightBarButtonItem:doneButton]; } } }
  • 很抱歉间距不佳,cmets 有字符限制。我假设您的意思是如何使用具有故事板屏幕截图的第一个示例删除完成按钮。
【解决方案2】:

如果您想要的是 iPad 上的弹出框,但 iPhone 上带有关闭按钮的模态表,那么您无需在情节提要中为弹出框创建额外的导航控制器即可。

在 Xcode 6.3 故事板中,您只需连接一个视图控制器并将 segue 指定为“Present as 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       
    }
    

    然后,一个简单的方法来实现弹出框的关闭行为,以防它全屏显示:

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

    你完成了!

    【讨论】:

    • 谢谢!好吧,当我问这个问题时,那是我的第一个 iOS 项目。我是一个完全的菜鸟。
    【解决方案4】:

    在我的例子中,我有一个小弹出窗口,我想成为 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
        }
    }
    

    【讨论】:

      【解决方案5】:

      可以使用最少的代码来实现,同时将逻辑放入情节提要中。在呈现弹出框的视图控制器中,只需放入标记方法

      @IBAction func unwindToContainerVC(segue: UIStoryboardSegue) {
      
      }
      

      它不需要任何代码,但需要存在,以便您稍后在使用界面生成器时控制拖动到退出图标。

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

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

      这是手势识别器的连接检查器:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-06
        • 1970-01-01
        • 2013-02-08
        • 2016-03-19
        • 2014-01-07
        • 1970-01-01
        相关资源
        最近更新 更多