ActionSheet Popover on iPad in Swift

Nick Meehan
3 min readNov 1, 2016

I recently ran into some problems while trying to show an ActionSheet popover for iPad working in Swift. A lot of the solutions I found were in Objective-C and didn’t necessarily fit what I was trying to accomplish.

If you are unfamiliar with ActionSheets, you can check out Apple’s human interface guidelines on them here.

If you’re developing specifically for iPhone, you just need to construct the alert controller and present it from your view controller in code and you’re done. In my implementation I am presenting from a button I linked with an @IBAction.

Which will give you this.

When building on iPad, the app crashes with this output.

*** Terminating app due to uncaught exception ‘NSGenericException’, reason: ‘Your application has presented a UIAlertController (<UIAlertController: 0x7f9d0ad52ca0>) of style UIAlertControllerStyleActionSheet. The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller’s popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.’

What? OK. So I need to present it as a popover. Cool.

For this to work, I need to set everything up before I present my alert controller. For ease, I want to go with providing the barButtonItem, since I don’t want to get involved with the CGRect class.

Here, I can take two approaches, either change my action function argument to accept a sender of type UIBarButtonItem or cast my AnyObject sender to be UIBarButtonItem. First, I’ll cast.

Or, I set the type in the function signature to be UIBarButtonItem.

Both of these result in the following.

Definitely not what I was looking for. I want the popover to appear centered in the view. So, I’ll need to go the route of using sourceView and sourceRect. Only the attributes of the popoverController need to be changed, so I’m only going to show that snippet of code.

A few things to note here:

  • I am no longer referencing barButtonItem, so be sure to remove the setting of this.
  • I am setting the sourceView of the popoverController to reference my current view controller’s view.
  • I am constructing the sourceRect by setting the x and y attributes of the rectangle’s origin to be the horizontal and vertical midpoint of the view, respectively, and leaving the width and height at 0, since we are only concerned with the origin point.

Which results in the following.

Close, but the arrow is pointing at the center of the view and not the popover. I need to remove the arrow.

This gives us exactly what we want!

Nice. All done.

Comments and feedback welcome.

--

--