Freelance iOS Developer, Rapidly Aging Punk

iPad Style Popovers on the iPhone with Swift

Nov 28, 2014 at 02:34PM

Xcode has a built-in adaptive segue called "Present As Popover" but by default it only behaves the way you'd expect it to — presenting a view in a speech-bubble style floating popover — on the iPad. On the iPhone your views are presented modally, full-screen. This is on purpose and is yet another subtle encouragement from Apple that we should build our apps with adaptivity in mind, but it's almost never what I actually want my popovers to do. Here's how to fix that.

Drag a new view controller onto your storyboard and tweak these settings:

Simulated Metrics Under "Simulated Metrics" change "Size" to "Freeform" and "Status Bar" to "None."

Simulated Size Under "Simulated Size" change your view's height and width to the actual size you want your popover's content to be.

Content Size Back on the attributes inspector check the box next to "Use Preferred Explicit Size" and make sure the height and width match the sizes you set in the previous step.

Drag a new segue from a control on your presenting view controller (a UIBarButtonItem is a good fit) to your popover view controller. Choose "popover presentation" from the dropdown and then give your segue an ID:

Segue ID

Open your view controller class file and add the UIPopoverPresentationControllerDelegate protocol:

class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {

Override the prepareForSegue function to catch your popover segue. Set the modalPresentationStyle to .Popover to explicitly state that you want a popover and then assign the delegate property of the view's popoverPresentationController to self:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "popoverSegue" {
            let popoverViewController = segue.destinationViewController as! UIViewController
            popoverViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
            popoverViewController.popoverPresentationController!.delegate = self
        }
    }

Finally, implement the adaptivePresentationStyleForPresentationController function to tell your app that you really want that popover presentation and will accept no substitutions:

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

Hello, there!

That's it.

Edited 4/24/15: Changed an as to an as! for Swift 1.2