iOS 8 iPhone上的UIPopoverPresentationController


75

有谁知道是否UIPopoverPresentationController可以在iPhone上显示弹出窗口?想知道苹果是否在iOS 8上添加了此功能,以试图为iPad和iPhone创建更统一的演示控制器。

不确定是否可以从Beta提问/回答问题。在这种情况下,我将其删除。

Answers:


84

您可以UIModalPresentationFullScreen使用提供的adaptivePresentationStyleForPresentationController:方法来覆盖默认的自适应行为(在紧凑的水平环境中,即iPhone) UIPopoverPresentationController.delegate

UIPresentationController使用此方法询问要使用的新演示文稿样式,在您的情况下,简单地返回UIModalPresentationNone将导致UIPopoverPresentationController呈现为弹出窗口而不是全屏。

这是使用情节提要中的segue设置将弹出窗口的示例从转换UIBarButtonItem为“模态呈现UIViewController

class SomeViewController: UIViewController, UIPopoverPresentationControllerDelegate {

    // override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) { // swift < 3.0
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "PopoverSegue" {
            if let controller = segue.destinationViewController as? UIViewController {
                controller.popoverPresentationController.delegate = self
                controller.preferredContentSize = CGSize(width: 320, height: 186)                
            }
        }
    }

    // MARK: UIPopoverPresentationControllerDelegate

    //func adaptivePresentationStyleForPresentationController(controller: UIPresentationController!) -> UIModalPresentationStyle { // swift < 3.0
    func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
        // Return no adaptive presentation style, use default presentation behaviour
        return .None
    }
}

WWDC 2014会议214“ iOS8中的View Controller Advancement”中提到了此技巧(36:30)


2
这在iPhone的GM中存在问题。如果您尝试在模拟器为人像时演示,则始终为全屏。如果旋转到横向,它将变成一个弹出框。如果再次旋转回纵向,它将保持弹出框。
jjxtra 2014年

17
解决方案是在调用presentViewController之前设置弹出窗口。这与Apple的示例正好相反,在Apple的示例中,它们显式地告诉您设置AFTER,然后调用presentViewController。
jjxtra 2014年

4
obj-c中针对无法阅读Swift的人的同一段代码:stackoverflow.com/a/28143620/1228075
Armin 2015年

@PsychoDad是正确的。我的逻辑和信任感崩溃了。不信任任何人,甚至不信任WWDC视频和Apple类参考。
丹尼尔(Daniel)

@丹尼尔确实。无论如何,在展示前进行设置会更加麻烦,而且苹果可能会在发布之前更改此设置。
jjxtra

75

如果有人只想显示带有代码的弹出窗口,则可以使用以下方法。

目标-C

声明以下属性UIPopoverPresentationController

@property(nonatomic,retain)UIPopoverPresentationController *dateTimePopover8;

使用以下方法显示UIButton的弹出窗口:

- (IBAction)btnSelectDatePressed:(id)sender
{
    UINavigationController *destNav = [[UINavigationController alloc] initWithRootViewController:dateVC];/*Here dateVC is controller you want to show in popover*/
    dateVC.preferredContentSize = CGSizeMake(280,200);
    destNav.modalPresentationStyle = UIModalPresentationPopover;
    _dateTimePopover8 = destNav.popoverPresentationController;
    _dateTimePopover8.delegate = self;
    _dateTimePopover8.sourceView = self.view;
    _dateTimePopover8.sourceRect = sender.frame;
    destNav.navigationBarHidden = YES;
    [self presentViewController:destNav animated:YES completion:nil];
}

使用以下方法显示UIBarButtonItem的弹出窗口:

- (IBAction)btnSelectDatePressed:(id)sender
{
    UINavigationController *destNav = [[UINavigationController alloc] initWithRootViewController:dateVC];/*Here dateVC is controller you want to show in popover*/
    dateVC.preferredContentSize = CGSizeMake(280,200);
    destNav.modalPresentationStyle = UIModalPresentationPopover;
    _dateTimePopover8 = destNav.popoverPresentationController;
    _dateTimePopover8.delegate = self;
    _dateTimePopover8.sourceView = self.view;
     CGRect frame = [[sender valueForKey:@"view"] frame];
    frame.origin.y = frame.origin.y+20;
    _dateTimePopover8.sourceRect = frame;
    destNav.navigationBarHidden = YES;
    [self presentViewController:destNav animated:YES completion:nil];
}

在您的视图控制器中也实现此委托方法:

- (UIModalPresentationStyle) adaptivePresentationStyleForPresentationController: (UIPresentationController * ) controller {
    return UIModalPresentationNone;
}

要关闭此弹出窗口,只需关闭视图控制器。下面是关闭视图控制器的代码:

-(void)hideIOS8PopOver
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

迅速

使用以下方法显示UIButon的弹出窗口:

func filterBooks(sender: UIButon)
    {
        let filterVC =  FilterDistanceViewController(nibName: "FilterDistanceViewController", bundle: nil)
        var filterDistanceViewController = UINavigationController(rootViewController: filterVC)
        filterDistanceViewController.preferredContentSize = CGSizeMake(300, 205)
        let popoverPresentationViewController = filterDistanceViewController.popoverPresentationController
        popoverPresentationViewController?.permittedArrowDirections = .Any
        popoverPresentationViewController?.delegate = self
        popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem
        popoverPresentationViewController!.sourceView = self.view;
        popoverPresentationViewController!.sourceRect = sender.frame

        filterDistanceViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
        filterDistanceViewController.navigationBarHidden = true
        self.presentViewController(filterDistanceViewController, animated: true, completion: nil)
    }

使用以下方法显示UIBarButtonItem的弹出窗口:

func filterBooks(sender: UIBarButtonItem)
    {
        let filterVC =  FilterDistanceViewController(nibName: "FilterDistanceViewController", bundle: nil)
        var filterDistanceViewController = UINavigationController(rootViewController: filterVC)
        filterDistanceViewController.preferredContentSize = CGSizeMake(300, 205)
        let popoverPresentationViewController = filterDistanceViewController.popoverPresentationController
        popoverPresentationViewController?.permittedArrowDirections = .Any
        popoverPresentationViewController?.delegate = self
        popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem
        popoverPresentationViewController!.sourceView = self.view;
        var frame:CGRect = sender.valueForKey("view")!.frame
        frame.origin.y = frame.origin.y+20
        popoverPresentationViewController!.sourceRect = frame

        filterDistanceViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
        filterDistanceViewController.navigationBarHidden = true
        self.presentViewController(filterDistanceViewController, animated: true, completion: nil)
    }

在您的视图控制器中也实现此委托方法:

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

请确保UIPopoverPresentationControllerDelegate在.h / .m / .swift文件中添加委托


这对我在横向模式下的iPhone上的iOS8 / Swift效果很好
leafcutter

1
我不认为需要声明UIPopoverPresentationController。当我简单地通过目标视图控制器访问并设置其属性时,它就对我有用。我正在使用Swift和Xcode 6.2。
丹尼尔(Daniel)

1
destNav.popoverPresentationController为零。
pronebird

如果您遇到此问题,请转至Apple错误地描述了如何配置弹出窗口文档,并单击“反馈”按钮并建议他们更正代码清单,以帮助其他人。
hwaxxer

1
不适合我的情况:dateVC初始化时没有Storyboard
Loc

11

问题: iPhone弹出窗口显示全屏,并且不遵守preferredContentSize值。

解决方案:与Apple在UIPopoverPresentationController类引用中建议的相反,在获得对popover呈现控制器的引用并对其进行配置之后,呈现视图控制器。

// Get the popover presentation controller and configure it.
//...

// Present the view controller using the popover style.
[self presentViewController:myPopoverViewController animated: YES completion: nil]; 

在这里做同样的事情,实现委托并还不够,在配置完之后演示了在iPhone 6S iOS 10.1上的窍门
dvkch

它的本质仅在于在presentViewController之前设置委托,
BugaBuga

3

确保实现UIAdaptivePresentationControllerDelegate

像这样:

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
    return UIModalPresentationNone;
}

如果您不想全屏弹出窗口


2

我找到了一些解决方法。

在Xcode6.1上,使用presentationController.delegate代替popoverPresentationController.delegate

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier compare:@"showPopOver"] == NSOrderedSame) {
        UINavigationController * nvc = segue.destinationViewController;
        UIPresentationController * pc = nvc.presentationController;
        pc.delegate = self;
    }
}

#pragma mark == UIPopoverPresentationControllerDelegate ==
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller
{
    return UIModalPresentationNone;
}

在WWDC 2014“ iOS8中的View Controller Advances”中,以下代码可以显示iPhone上的弹出窗口。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{

    UINavigationController * nvc = segue.destinationViewController;
    UIPopoverPresentationController * pvc = nvc.popoverPresentationController;
    pvc.delegate = self;
}

#pragma mark == UIPopoverPresentationControllerDelegate ==
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller
{
    return UIModalPresentationNone;
}

但是在Xcode 6.1上,这些代码显示了FullScreen演示...(nvc.popoverPresentationController为nil)

我怀疑这可能是苹果的错误。


1

在iOS 8.3和更高版本中,请在UIPopoverPresentationControllerDelegate协议中使用以下语法来覆盖弹出窗口的UIModalPresentationStyle

func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
    return .none
}

0

在您的WEBVIEW类中添加这两个方法。并添加

-(void) prepareForSegue: (UIStoryboardSegue * ) segue sender: (id) sender {
    // Assuming you've hooked this all up in a Storyboard with a popover presentation style
    if ([segue.identifier isEqualToString: @"showPopover"]) {
        UINavigationController * destNav = segue.destinationViewController;
        pop = destNav.viewControllers.firstObject;
        // This is the important part
        UIPopoverPresentationController * popPC = destNav.popoverPresentationController;
        popPC.delegate = self;
    }
}

- (UIModalPresentationStyle) adaptivePresentationStyleForPresentationController: (UIPresentationController * ) controller {
    return UIModalPresentationNone;
}

0

您可以像这样扩展UIPopoverPresentationControllerDelegate:

protocol PopoverPresentationSourceView {}
extension UIBarButtonItem : PopoverPresentationSourceView {}
extension UIView : PopoverPresentationSourceView {}

extension UIPopoverPresentationControllerDelegate where Self : UIViewController {
   func present(popover: UIViewController, 
        from sourceView: PopoverPresentationSourceView, 
        size: CGSize, arrowDirection: UIPopoverArrowDirection) {

      popover.modalPresentationStyle = .popover
      popover.preferredContentSize = size
      let popoverController = popover.popoverPresentationController
      popoverController?.delegate = self
      if let aView = sourceView as? UIView {
          popoverController?.sourceView = aView
          popoverController?.sourceRect = CGRect(x: aView.bounds.midX, y: aView.bounds.midY, width: 0, height: 0)
      } else if let barButtonItem = sourceView as? UIBarButtonItem {
          popoverController?.barButtonItem = barButtonItem
      }
      popoverController?.permittedArrowDirections = arrowDirection
      present(popover, animated: true, completion: nil)
   }
}

现在,您可以present(popover: from: size: arrowDirection: )从实现UIPopoverPresentationControllerDelegate例如的任何视图控制器中调用。

class YourViewController : UIViewController {
    @IBAction func someButtonPressed(_ sender: UIButton) {
        let popover = SomeViewController()
        present(popover: popover, from: sender, size: CGSize(width: 280, height: 400), arrowDirection: .right)
    }
}

extension YourViewController : UIPopoverPresentationControllerDelegate {
    func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
        return .none
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.