How to create Popovers in iOS 9

iOS 8 introduced a new way of creating Popovers on iPad: instead of using the trusty old (nightmarish) UIPopoverController class, we can now use the UIPopoverPresentationController. It’s available on iPads as well as iPhones.

The great news for us developers is that we no longer have to check what type of device we’re on and present our content accordingly: we simply present a Popover, and if we happen to be on an iPhone, iOS will automatically show our view controller as an action sheet instead. No other code change or if-then query is necessary.

While this approach was optional in iOS 8, the UIPopoverController is now deprecated and should no longer be used in iOS 9 (and good riddens I say). Both the creation as well as dismissal process have been streamlined, and I find it’s now actually a joy rather than a chore to play with Popovers.

Let’s see how to create a simple Popover Presentation Controller in iOS 9.

Popover Basics

The concept of a Popover is still the same: we need a content view controller that’s displayed inside the Popover, while the Popover itself is a different object (now called the Popover presentation controller). The view controller can have a custom class (for the UI and logic that’s presented therein), while the presentation controller does not require any additional code.

To react to the dismissal of a Popover we can implement a delegate. We’ll see how this works in a moment.

Presenting a Popover from a Bar Button Item

Popovers need an anchor, such as a UIBarButtonItem in a navigation controller. I have a reference to it, so this following Popover can point its arrow at it:

Here’s what we do step by step: first we grab our content view controller. I’m instantiating one from my main storyboard. Make sure the Storyboard ID is set in Interface Builder so we can reference it. On iPhone, we could go ahead and present the view controller at this point, but because we want to be Popover-Compatible, we’ll do a little extra work.

Next I’m setting the modal presentation style of my view controller to UIModalPresentationPopover. This tells iOS that if possible, we want to see our content presented as a Popover. Now we show the view controller, even though it won’t be presented until we’re done with our next step.

We need to create a UIPopoverPresentationController object and configure it (i.e. instantiate with our content view controller, set the delegate, anchor point, etc). And that’s it: now iOS will show our content. If we’re on an iPad, it will now be shown in a Popover. If we’re on an iPhone or iPod it’ll show as an action sheet.

I know this looks weird: we seemingly present the view controller first, and then we configure the presentation controller. Even for Mr. Spock this would be highly illogical. However, according to the Apple documentation, UIKit will only ask for a presentation controller when the content view controller starts its presentation.

Try it out, it works like a charm!

Presenting a Popover from an arbitrary anchor point

We don’t need to use a bar button item as an anchor point. Instead we can use the sourceView and sourceRect properties of the presentation controller to set its origin:

Experiment with the rectangle values to find the correct placement for Popovers presented this way. The first two describe x/y coordinates for where the top left corner of the Popover starts, while the last two describe the size of the frame around the Popover (I think).

Dismissing a Popover

When a user taps on the outside of our new Popover, it is dismissed automatically – if we wish for this to happen. No additional work on our part is needed to make that happen.

What was slightly tricky with the old UIPopoverController class was to dismiss a Popover as a result of an action inside the content view controller. Lucky for us this is now super easy: simply call the content view controller’s dismissViewcontroller method, and the Popover is dismissed without crashes! Hurra!

In your custom content view controller class, you may have code like this. Call it when you want the Popover to go away:

Objective-C

1

2

3

4

-(void)dismissMe{

[self dismissViewControllerAnimated:YES completion:nil];

}

Overall this is now just a modal presentation with a different style. Therefore, exchanging data is as easy as it is with non-Popover presentations.

Reacting to Popover Dismissal

There’s a new protocol in town called the UIPopoverPresentationControllerDelegate that is called upon dismissal and position change due to rotation or interface changes. We can even prevent a Popover from being dismissed if we wish. Here are the three methods we can implement:

Share this:

Related

About Jay Versluis

Jay is a medical miracle known as Super Survivor. He runs two YouTube channels, five websites and several podcast feeds. To see what else he's up to, and to support him on his mission to make the world a better place, check out his Patreon Campaign.
View all posts by Jay Versluis →

Perhaps I should have said “SHOULD no longer be used” – thanks for pointing that out. Deprecated doesn’t meant “stopped working overnight”, but rather “should not be used going forward”: https://en.wikipedia.org/wiki/Deprecation

Hi Alvaro, there’s no magic formula for state preservation with Popovers, like there is with table views for example. If you need this functionality, your only option is to save the state of each UI element manually, and bring it back when the Popover is needed again.

First, thanks for this post, it help me a lot.
In second, i have found a key to do the initialization of popup in some different way. The key problem is that “popoverPresentationController” property of ViewController in popup will not be initialized until “modalPresentationStyle” property of that controller not set to UIModalPresentationPopover (.Popover in swift). Here is my working code in swift, as you see, presentViewController goes after all setup done: