ActionSheet Popover on iPad in Swift
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 thepopoverController
to reference my current view controller’s view. - I am constructing the
sourceRect
by setting thex
andy
attributes of the rectangle’s origin to be the horizontal and vertical midpoint of the view, respectively, and leaving thewidth
andheight
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.