Presenting a UIAlertController properly on an iPad using iOS 8 Presenting a UIAlertController properly on an iPad using iOS 8 ios ios

Presenting a UIAlertController properly on an iPad using iOS 8


You can present a UIAlertController from a popover by using UIPopoverPresentationController.

In Obj-C:

UIViewController *self; // code assumes you're in a view controllerUIButton *button; // the button you want to show the popup sheet fromUIAlertController *alertController;UIAlertAction *destroyAction;UIAlertAction *otherAction;alertController = [UIAlertController alertControllerWithTitle:nil                                                      message:nil                           preferredStyle:UIAlertControllerStyleActionSheet];destroyAction = [UIAlertAction actionWithTitle:@"Remove All Data"                                         style:UIAlertActionStyleDestructive                                       handler:^(UIAlertAction *action) {                                           // do destructive stuff here                                       }];otherAction = [UIAlertAction actionWithTitle:@"Blah"                                       style:UIAlertActionStyleDefault                                     handler:^(UIAlertAction *action) {                                         // do something here                                     }];// note: you can control the order buttons are shown, unlike UIActionSheet[alertController addAction:destroyAction];[alertController addAction:otherAction];[alertController setModalPresentationStyle:UIModalPresentationPopover];UIPopoverPresentationController *popPresenter = [alertController                                               popoverPresentationController];popPresenter.sourceView = button;popPresenter.sourceRect = button.bounds;[self presentViewController:alertController animated:YES completion:nil];

Editing for Swift 4.2, though there are many blogs available for the same but it may save your time to go and search for them.

if let popoverController = yourAlert.popoverPresentationController {    popoverController.sourceView = self.view //to set the source of your alert    popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0) // you can set this as per your requirement.    popoverController.permittedArrowDirections = [] //to hide the arrow of any particular direction}


On iPad the alert will be displayed as a popover using the new UIPopoverPresentationController, it requires that you specify an anchor point for the presentation of the popover using either a sourceView and sourceRect or a barButtonItem

  • barButtonItem
  • sourceView
  • sourceRect

In order to specify the anchor point you will need to obtain a reference to the UIAlertController's UIPopoverPresentationController and set one of the properties as follows:

alertController.popoverPresentationController.barButtonItem = button;

sample code:

UIAlertAction *actionDelete = nil;UIAlertAction *actionCancel = nil;// create action sheetUIAlertController *alertController = [UIAlertController                                      alertControllerWithTitle:actionTitle message:nil                                      preferredStyle:UIAlertControllerStyleActionSheet];// Delete ButtonactionDelete = [UIAlertAction                actionWithTitle:NSLocalizedString(@"IDS_LABEL_DELETE", nil)                style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {                    // Delete                    // [self deleteFileAtCurrentIndexPath];                }];// Cancel ButtonactionCancel = [UIAlertAction                actionWithTitle:NSLocalizedString(@"IDS_LABEL_CANCEL", nil)                style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {                    // cancel                    // Cancel code                }];// Add Cancel action[alertController addAction:actionCancel];[alertController addAction:actionDelete];// show action sheetalertController.popoverPresentationController.barButtonItem = button;alertController.popoverPresentationController.sourceView = self.view;[self presentViewController:alertController animated:YES                 completion:nil];


In Swift 2, you want to do something like this to properly show it on iPhone and iPad:

func confirmAndDelete(sender: AnyObject) {    guard let button = sender as? UIView else {        return    }    let alert = UIAlertController(title: NSLocalizedString("Delete Contact?", comment: ""), message: NSLocalizedString("This action will delete all downloaded audio files.", comment: ""), preferredStyle: .ActionSheet)    alert.modalPresentationStyle = .Popover    let action = UIAlertAction(title: NSLocalizedString("Delete", comment: ""), style: .Destructive) { action in        EarPlaySDK.deleteAllResources()    }    let cancel = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel) { action in    }    alert.addAction(cancel)    alert.addAction(action)    if let presenter = alert.popoverPresentationController {        presenter.sourceView = button        presenter.sourceRect = button.bounds    }    presentViewController(alert, animated: true, completion: nil)}

If you don't set the presenter, you will end up with an exception on iPad in -[UIPopoverPresentationController presentationTransitionWillBegin] with the following message:

Fatal Exception: NSGenericException Your application has presented a UIAlertController (<UIAlertController: 0x17858a00>) 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.