如何知道视图控制器是否将呈现为弹出窗口或模式?
How to know if a view controller will be presented as a popover or modal?
在呈现视图控制器之前,我将 modalPresentationStyle
属性 设置为 UIModalPresentationPopover
。当 运行 在具有常规水平尺寸 class 的设备上(iPad 和 iPhone 6+ 横向)和 modal/fullscreen 在其他设备上。也可以通过覆盖 adaptivePresentationStyleForPresentationController
来覆盖此行为,以便视图控制器在所有设备上显示为弹出窗口。
我想知道是否有可能在呈现视图控制器之后知道它是否呈现为弹出窗口?只看大小 class 是不行的,因为视图控制器可能会覆盖 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;
这是检测视图控制器是否显示为弹出窗口的当前代码。但如上所述,它只查看大小 class,这并不适用于所有情况。
+ (BOOL)willPresentTruePopover:(id<UITraitEnvironment>)vc {
return ([vc traitCollection].horizontalSizeClass == UIUserInterfaceSizeClassRegular);
}
我在 UIViewController
或 UIPopoverPresentationController
(或其他任何地方)中找不到任何 属性 或函数可以立即给我提供此信息,但也许我遗漏了什么?
使用UIAdaptivePresentationControllerDelegate
方法presentationController:willPresentWithAdaptiveStyle:transitionCoordinator:
。要在其他时间查询表示样式,请向表示控制器询问其 adaptivePresentationStyleForTraitCollection:
,并传递当前特征。这些方法是在 iOS 8.3 中添加的,并且是 not documented yet.
你说你试图这样做是为了删除 cancel/done 按钮。相反,只在需要时才添加按钮。
实现这个的官方方法是首先从你的视图控制器中删除完成按钮,其次,当适应紧凑地将你的视图控制器嵌入到导航控制器中时,现在将完成按钮添加为导航项:
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)
}
我正在以与您相同的方式攻击它,因为我在 Interface Builder 中设置了“完成”按钮及其目标操作。为了删除它,我正在测试 popoverPresentationController != nil 是否存在。在我的测试设备 (iPhone 5 运行 iOS 10) 上,此测试在 iPad Pro 运行 上执行时成功忽略了 iPhone iOS 11. 我 运行 在 iPhone 8 运行 iOS 上测试它时遇到问题 11. 它出现在 iOS 11 中 popoverPresentationController 是现在即使在模态呈现视图时也会实例化。因此,我只是在测试呈现视图控制器的水平尺寸 class。不确定这是否是正确的方法,但它对我有用,因为我找不到任何方法让 popoverPresentationController 告诉我它实际上是模态呈现的。
weak var ppcDelegate: UIPopoverPresentationControllerDelegate?
...
if popoverPresentationController != nil &&
popoverPresentationController!.presentingViewController.traitCollection.horizontalSizeClass == .regular {
navigationItem.rightBarButtonItem = nil
popoverPresentationController?.delegate = ppcDelegate
}
在呈现视图控制器之前,我将 modalPresentationStyle
属性 设置为 UIModalPresentationPopover
。当 运行 在具有常规水平尺寸 class 的设备上(iPad 和 iPhone 6+ 横向)和 modal/fullscreen 在其他设备上。也可以通过覆盖 adaptivePresentationStyleForPresentationController
来覆盖此行为,以便视图控制器在所有设备上显示为弹出窗口。
我想知道是否有可能在呈现视图控制器之后知道它是否呈现为弹出窗口?只看大小 class 是不行的,因为视图控制器可能会覆盖 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;
这是检测视图控制器是否显示为弹出窗口的当前代码。但如上所述,它只查看大小 class,这并不适用于所有情况。
+ (BOOL)willPresentTruePopover:(id<UITraitEnvironment>)vc {
return ([vc traitCollection].horizontalSizeClass == UIUserInterfaceSizeClassRegular);
}
我在 UIViewController
或 UIPopoverPresentationController
(或其他任何地方)中找不到任何 属性 或函数可以立即给我提供此信息,但也许我遗漏了什么?
使用UIAdaptivePresentationControllerDelegate
方法presentationController:willPresentWithAdaptiveStyle:transitionCoordinator:
。要在其他时间查询表示样式,请向表示控制器询问其 adaptivePresentationStyleForTraitCollection:
,并传递当前特征。这些方法是在 iOS 8.3 中添加的,并且是 not documented yet.
你说你试图这样做是为了删除 cancel/done 按钮。相反,只在需要时才添加按钮。
实现这个的官方方法是首先从你的视图控制器中删除完成按钮,其次,当适应紧凑地将你的视图控制器嵌入到导航控制器中时,现在将完成按钮添加为导航项:
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)
}
我正在以与您相同的方式攻击它,因为我在 Interface Builder 中设置了“完成”按钮及其目标操作。为了删除它,我正在测试 popoverPresentationController != nil 是否存在。在我的测试设备 (iPhone 5 运行 iOS 10) 上,此测试在 iPad Pro 运行 上执行时成功忽略了 iPhone iOS 11. 我 运行 在 iPhone 8 运行 iOS 上测试它时遇到问题 11. 它出现在 iOS 11 中 popoverPresentationController 是现在即使在模态呈现视图时也会实例化。因此,我只是在测试呈现视图控制器的水平尺寸 class。不确定这是否是正确的方法,但它对我有用,因为我找不到任何方法让 popoverPresentationController 告诉我它实际上是模态呈现的。
weak var ppcDelegate: UIPopoverPresentationControllerDelegate?
...
if popoverPresentationController != nil &&
popoverPresentationController!.presentingViewController.traitCollection.horizontalSizeClass == .regular {
navigationItem.rightBarButtonItem = nil
popoverPresentationController?.delegate = ppcDelegate
}