【问题标题】:How to know if a view controller will be presented as a popover or modal?如何知道视图控制器是否将呈现为弹出框或模式?
【发布时间】:2015-12-10 08:31:34
【问题描述】:

在展示视图控制器之前,我将modalPresentationStyle 属性设置为UIModalPresentationPopover。这将在具有常规水平尺寸类的设备(iPad 和 iPhone 6+ 横向)上运行时将视图控制器显示为弹出框,并在其他设备上显示为模态/全屏。也可以通过覆盖 adaptivePresentationStyleForPresentationController 来覆盖此行为,以便视图控制器在所有设备上显示为弹出框。

我想知道在呈现视图控制器之后是否有可能知道它是否呈现为弹出框?仅查看 size 类是行不通的,因为视图控制器可能会覆盖 adaptivePresentationStyleForPresentationController

显而易见的答案是,作为程序员,我应该知道我是否覆盖adaptivePresentationStyleForPresentationController,但我想编写一个函数,可以通过传入视图控制器或可能在运行时为任何视图控制器确定这一点UIPopoverPresentationController(或任何其他需要的对象)作为参数。

下面是一些展示视图控制器的代码:

navigationController = (UINavigationController *)[MVSStore sharedInstance].addViewController;
navigationController.modalPresentationStyle = UIModalPresentationPopover;
[self presentViewController:navigationController animated:YES completion:^{}];

UIPopoverPresentationController *popoverController = navigationController.popoverPresentationController;
popoverController.sourceView = self.view;
popoverController.sourceRect = CGRectMake(20, 20, 20, 20); // Just a dummy
popoverController.permittedArrowDirections = UIPopoverArrowDirectionAny;

这是检测视图控制器是否显示为弹出框的当前代码。但如上所述,它只查看不适用于所有情况的尺寸等级。

+ (BOOL)willPresentTruePopover:(id<UITraitEnvironment>)vc {
    return ([vc traitCollection].horizontalSizeClass == UIUserInterfaceSizeClassRegular);
}

我在 UIViewControllerUIPopoverPresentationController(或其他任何地方)中找不到任何可以立即为我提供此信息的属性或函数,但也许我遗漏了什么?

【问题讨论】:

  • 只是好奇,你为什么想知道?
  • 我会用它来显示或隐藏取消按钮。在弹出窗口的情况下,我不需要显示取消按钮,因为通过点击外部视图控制器会关闭视图控制器。另一个原因是在关闭视图控制器时更新父视图控制器。这目前在父级的 viewWillAppear 和 viewDidAppear 中完成。然而,当子视图控制器显示为弹出框(但它们是模态时)时,不会调用 viewDidAppear 和 viewWillAppear,因此我需要以某种方式处理这种特殊情况。
  • @Markus 我添加了一个答案,显示如何仅在需要时添加取消按钮。

标签: ios iphone ipad uikit popover


【解决方案1】:

您说您试图这样做是为了删除取消/完成按钮。而是只在需要的情况下添加按钮。

实现这一点的官方方法是首先从您的视图控制器中删除完成按钮,其次,当适应紧凑型将您的视图控制器嵌入到导航控制器中时,现在将完成按钮添加为导航项:

func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
    return UIModalPresentationStyle.FullScreen
}

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

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

Full Tutorial

【讨论】:

    【解决方案2】:

    我以与您相同的方式攻击它,因为我在 Interface Builder 中设置了 Done 按钮及其目标操作。为了删除它,我正在测试 popoverPresentationController 是否!= nil。在我的测试设备(运行 iOS 10 的 iPhone 5)上,该测试在运行 iOS 11 的 iPad Pro 上执行时成功忽略了 iPhone。我在运行 iOS 11 的 iPhone 8 上测试它时遇到了问题。在 iOS 11 中出现即使在模态显示视图时,popoverPresentationController 现在也会被实例化。因此,我只是在测试呈现视图控制器的水平尺寸类。不确定这是否是正确的方法,但它对我有用,因为我找不到任何方法让 popoverPresentationController 告诉我它实际上是模态呈现。

        weak var ppcDelegate: UIPopoverPresentationControllerDelegate?
    

    ...

        if popoverPresentationController != nil && 
            popoverPresentationController!.presentingViewController.traitCollection.horizontalSizeClass == .regular {
    
            navigationItem.rightBarButtonItem = nil
            popoverPresentationController?.delegate = ppcDelegate
        }
    

    【讨论】:

      【解决方案3】:

      使用UIAdaptivePresentationControllerDelegate 方法presentationController:willPresentWithAdaptiveStyle:transitionCoordinator:。要在其他时间查询演示样式,请向演示控制器询问其adaptivePresentationStyleForTraitCollection:,并传递当前特征。这些方法是在 iOS 8.3 中添加的,它们是not documented yet

      【讨论】:

      • 我没有设法相应地设置委托以使其工作。设置视图控制器类以符合 UIAdaptivePresentationControllerDelegate 然后使用 popoverController.delegate = self;编译但我收到一条警告,提示 self 不符合 UIPopoverPresentationControllerDelegate 并且 willPresent... 函数未被调用。如果 vc 符合 UIPopoverPresentationControllerDelegate 而是编译但函数未被调用,因为 UIPopoverPresentationControllerDelegate 不公开此函数(即使它符合 UIAdaptivePresentationControllerDelegate 本身。)
      • 好吧,我设法让它工作了。它实际上工作正常,但我对使用未记录的功能不是很有信心......我听说有人在 AppStore 审查时间上苦苦挣扎。我也宁愿找到一个适用于 iOS 8.0 的解决方案。
      • 哦,这些是无证的,因为他们还没有开始记录它们。这些方法存在于公共标头中,非常适合 App Store 审查。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-21
      • 2016-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多