UIPopoverPresentationController on iOS 8 iPhone UIPopoverPresentationController on iOS 8 iPhone objective-c objective-c

UIPopoverPresentationController on iOS 8 iPhone


You can override the default adaptive behaviour (UIModalPresentationFullScreen in compact horizontal environment, i.e. iPhone) using the adaptivePresentationStyleForPresentationController: method available through UIPopoverPresentationController.delegate.

UIPresentationController uses this method to ask the new presentation style to use, which in your case, simply returning UIModalPresentationNone will cause the UIPopoverPresentationController to render as a popover instead of fullscreen.

Here's an example of the popover using a segue setup in storyboard from a UIBarButtonItem to "present modally" a 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    }}

This trick was mentioned in WWDC 2014 session 214 "View Controller Advancement in iOS8" (36:30)


If anybody wants to present a popover with code only, you can use the following approach.

OBJECTIVE - C

Declare a property of UIPopoverPresentationController:

@property(nonatomic,retain)UIPopoverPresentationController *dateTimePopover8;

Use the following method to present the popover from 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];}

Use the following method to present the popover from 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];}

Implement this delegate method too in your view controller:

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

To dismiss this popover, simply dismiss the view controller. Below is the code to dismiss the view controller:

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

SWIFT

Use the following method to present the popover from 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)    }

Use the following method to present the popover from 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)    }

Implement this delegate method too in your view controller:

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

Please make sure to add delegate UIPopoverPresentationControllerDelegate in .h/.m/.swift file


PROBLEM: iPhone popover displays fullscreen and does not respect preferredContentSize value.

SOLUTION: Contrary to what Apple suggests in the UIPopoverPresentationController Class reference, presenting the view controller after getting a reference to the popover presentation controller and configuring it.

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