Ios8 iOS 8 presentationController确定是否真的是popover

Ios8 iOS 8 presentationController确定是否真的是popover,ios8,uipopovercontroller,adaptive-layout,Ios8,Uipopovercontroller,Adaptive Layout,我正在使用iOS 8新的自适应“显示为Popover”功能。我在故事板上编了一个简单的片段来做演示。它在iphone6plus上工作得非常好,因为它将视图显示为popover,在iphone4s上显示为全屏视图(活页样式) 问题是当显示为全屏视图时,我需要在视图中添加一个“完成”按钮,以便调用dismissViewControllerAnimated。我不想在显示为popover时显示“完成”按钮 NSLog( @"View loaded %lx", (long)self.presentatio

我正在使用iOS 8新的自适应“显示为Popover”功能。我在故事板上编了一个简单的片段来做演示。它在iphone6plus上工作得非常好,因为它将视图显示为popover,在iphone4s上显示为全屏视图(活页样式)

问题是当显示为全屏视图时,我需要在视图中添加一个“完成”按钮,以便调用dismissViewControllerAnimated。我不想在显示为popover时显示“完成”按钮

NSLog( @"View loaded %lx", (long)self.presentationController.adaptivePresentationStyle );          // UIModalPresentationFullScreen
NSLog( @"View loaded %lx", (long)self.presentationController.presentationStyle );                  // UIModalPresentationPopover
NSLog( @"View loaded %lx", (long)self.popoverPresentationController.adaptivePresentationStyle );   // UIModalPresentationFullScreen
NSLog( @"View loaded %lx", (long)self.popoverPresentationController.presentationStyle );           // UIModalPresentationPopover

我试着查看presentationController和popoverPresentationController的属性,但我找不到任何东西可以告诉我它是否实际显示为popover

NSLog( @"View loaded %lx", (long)self.presentationController.adaptivePresentationStyle );          // UIModalPresentationFullScreen
NSLog( @"View loaded %lx", (long)self.presentationController.presentationStyle );                  // UIModalPresentationPopover
NSLog( @"View loaded %lx", (long)self.popoverPresentationController.adaptivePresentationStyle );   // UIModalPresentationFullScreen
NSLog( @"View loaded %lx", (long)self.popoverPresentationController.presentationStyle );           // UIModalPresentationPopover
adaptivePresentationStyle始终返回UIModalPresentationFullScreen,presentationStyle始终返回UIModalPresentationPopover


在查看UITraitCollection时,我确实发现了一个名为“\u UITraitNameInteractionModel”的特性,当它实际显示为Popover时,该特性仅设置为1。然而,苹果并没有通过跟踪收集popoverPresentationController来提供对该特性的直接访问。

管理视图控制器的
UIPresentationController
通过将
modalPresentationStyle
设置为
UIModalPresentationPopover
来呈现视图控制器

根据
UIViewController

显示视图控制器

  • 显示此视图的视图控制器 控制器。(只读)
模态表示风格

  • UIModalPresentationPopover:在水平规则环境中,内容显示在popover视图中的一种表示样式。背景内容变暗并点击 在popover之外,导致popover被解雇。如果你不 要关闭弹出窗口,可以将一个或多个视图指定给 关联对象的passthroughview属性 UIPopoverPresentationController对象,可以从 popoverPresentationController属性
因此,我们可以通过如下检查
horizontalSizeClass
来确定您的视图控制器是在popover中还是以模式显示(我假设您的按钮是
UIBarButtonim


检查这一点最安全的地方是在
视图中将出现:
,否则
显示的iewcontroller
可能是
nil

我检查视图布局后是否设置了popoverPresentationController的箭头方向。就我的目的而言,这已经足够好了,并且涵盖了较小屏幕设备上的弹出框

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    if (popoverPresentationController?.arrowDirection != UIPopoverArrowDirection.Unknown) {
        // This view controller is running in a popover
        NSLog("I'm running in a Popover")
    }
}
怎么样

if (self.modalPresentationStyle == UIModalPresentationPopover)
这对我来说很有效

我发现最好的方法(最不难闻)就是使用
UIPopoverPresentationControllerDelegate

•确保显示的视图控制器设置为用于管理显示的
uipoperpresentationcontroller
上的
uipoperpresentationcontrollerdelegate
。我使用的是故事板,所以在
prepareforsgue:

segue.destinationViewController.popoverPresentationController.delegate = presentedVC;
•在显示的视图控制器中创建属性以跟踪此状态:

@property (nonatomic, assign) BOOL amDisplayedInAPopover;
•并添加以下委托方法(或添加到现有委托方法):

•然后最后在
视图中将出现:
-
视图加载:
太早了,在
视图加载:
视图将出现:

if (self.amDisplayedInAPopover) {
    // Hide the offending buttons in whatever manner you do so
    self.navigationItem.leftBarButtonItem = nil;
}
编辑:更简单的方法

只需设置代理(确保演示的DVC采用
UIPopoverPresentationControllerDelegate
):

并提供以下方法:

- (void)prepareForPopoverPresentation:(UIPopoverPresentationController *)popoverPresentationController
{
    // This method is only called if we are presented in a popover
    // Hide the offending buttons in whatever manner you do so
    self.navigationItem.leftBarButtonItem = nil;
}

实现这一点的正式方法是首先从视图控制器中删除“完成”按钮,然后在适应compact时将视图控制器嵌入到导航控制器中,将“完成”按钮添加为导航项:

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)
}


我测试了本文中介绍的所有解决方案。抱歉,在所有情况下都不能正常工作。例如,在iPad中,当拖动拆分视图线时,拆分视图显示样式可能会发生变化,因此我们需要对此进行特定的通知。 经过几个小时的研究,我在苹果样品(swift)中找到了解决方案:

以下是obj-c中的相同解决方案

在prepareForSegue函数中,首先设置popoverPresentationController委托。它也可以在MyViewController“init”中设置,但不能在“viewDidLoad”中设置(因为在viewDidLoad之前调用first willPresentWithAdaptiveStyle)

现在,每当iOS更改演示样式(包括首次演示)时,MyViewController对象都会收到此通知。下面是显示/隐藏navigationController中“关闭”按钮的示例实现:

- (void)presentationController:(UIPresentationController *)presentationController
  willPresentWithAdaptiveStyle:(UIModalPresentationStyle)style
         transitionCoordinator:(nullable id<UIViewControllerTransitionCoordinator>)transitionCoordinator {
    if (style == UIModalPresentationNone) {
        // style set in storyboard not changed (popover), hide close button
        self.topViewController.navigationItem.leftBarButtonItem = nil;
    } else {
        // style changed by iOS (to fullscreen or page sheet), show close button
        UIBarButtonItem *closeButton =
            [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(closeAction)];
        self.topViewController.navigationItem.leftBarButtonItem = closeButton;
    }
}

- (void)closeAction {
    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
-(void)presentationController:(UIPresentationController*)presentationController
将使用AdaptiveStyle:(UIModalPresentationStyle)样式呈现
transitionCoordinator:(可为null的id)transitionCoordinator{
if(style==UIModalPresentationNone){
//情节提要中的样式集未更改(popover),隐藏关闭按钮
self.topViewController.navigationItem.LeftBarButtonim=nil;
}否则{
//iOS更改的样式(全屏或页面),显示关闭按钮
UIBarButtonItem*关闭按钮=
[[UIBarButtonItem alloc]initWithTitle:@“关闭”样式:UIBarButtonItemStylePlain目标:自我操作:@selector(closeAction)];
self.topViewController.navigationItem.leftBarButtonItem=closeButton;
}
}
-(无效)封闭行动{
[self.presentingViewController dismissViewControllerAnimated:YES完成:nil];
}

多任务解决方案

将演示控制器指定为popover的委托

...
controller.popoverPresentationController.delegate = controller;
[self presentViewController:controller animated:YES completion:nil];
然后,在控制器中,实现委托方法:

- (void)presentationController:(UIPresentationController *)presentationController willPresentWithAdaptiveStyle:(UIModalPresentationStyle)style transitionCoordinator:(id<UIViewControllerTransitionCoordinator>)transitionCoordinator
{
    if (style != UIModalPresentationNone)
    {
        // Exited popover mode
        self.navigationItem.leftBarButtonItem = button;
    }
}

- (void)prepareForPopoverPresentation:(UIPopoverPresentationController *)popoverPresentationController
{
    // Entered popover mode
    self.navigationItem.leftBarButtonItem = nil;
}
-(void)presentationController:(UIPresentationController*)presentationController将与AD一起显示
- (void)presentationController:(UIPresentationController *)presentationController
  willPresentWithAdaptiveStyle:(UIModalPresentationStyle)style
         transitionCoordinator:(nullable id<UIViewControllerTransitionCoordinator>)transitionCoordinator {
    if (style == UIModalPresentationNone) {
        // style set in storyboard not changed (popover), hide close button
        self.topViewController.navigationItem.leftBarButtonItem = nil;
    } else {
        // style changed by iOS (to fullscreen or page sheet), show close button
        UIBarButtonItem *closeButton =
            [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(closeAction)];
        self.topViewController.navigationItem.leftBarButtonItem = closeButton;
    }
}

- (void)closeAction {
    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
...
controller.popoverPresentationController.delegate = controller;
[self presentViewController:controller animated:YES completion:nil];
- (void)presentationController:(UIPresentationController *)presentationController willPresentWithAdaptiveStyle:(UIModalPresentationStyle)style transitionCoordinator:(id<UIViewControllerTransitionCoordinator>)transitionCoordinator
{
    if (style != UIModalPresentationNone)
    {
        // Exited popover mode
        self.navigationItem.leftBarButtonItem = button;
    }
}

- (void)prepareForPopoverPresentation:(UIPopoverPresentationController *)popoverPresentationController
{
    // Entered popover mode
    self.navigationItem.leftBarButtonItem = nil;
}
if (self.view.superview!.bounds != UIScreen.main.bounds) {
    print("This is a popover!")
}