user619804 user619804 - 1 month ago 26
iOS Question

UIAlertController and displayShareSheet crashing on iPad

I have a UIButton within a view. The UIButton is positioned like

enter image description here

I have an @IBAction that is triggered when a UIButton is clicked

@IBAction func shareButtonClicked(_ sender: AnyObject) {
Flurry.logEvent("Share button tapped");


let textToShare = quotetext.text

// 1.
// Create and initialize a UIAlertController instance.
//
let alertController = UIAlertController(title: nil,
message: nil,
preferredStyle: .actionSheet)

// 2.
// Initialize the actions to show along with the alert.
//
let copyAction = UIAlertAction(title:"Copy Quote to clipboard",
style: .default) { (action) -> Void in
let pasteboard: UIPasteboard = UIPasteboard.general
pasteboard.string = self.quotetext.text;
}

let defaultAction = UIAlertAction(title:"Share Quote",
style: .default) { (action) -> Void in
// We have contents so display the share sheet
self.displayShareSheet(shareContent: textToShare)

}

let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action) in
// ...
}

// 3.
// Tell the alertController about the actions we want it
// to present.
//
alertController.addAction(copyAction)
alertController.addAction(defaultAction)
alertController.addAction(cancelAction)


// 4.
// Present the alert controller and associated actions.
//
self.present(alertController, animated: true, completion: nil)

}


This produces an alert that looks like

enter image description here

When 'Share Quote' is selected, the alert brings up a shareSheet.

This @IBAction works on iPhone, but is crashing on the iPad. The error message is


'NSGenericException', reason: 'Your application has presented a
UIAlertController () 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.'


I have tried to fix this problem by trying something like

//iPad

alertController.popoverPresentationController?.sourceView = viewBottom
alertController.popoverPresentationController?.sourceRect = viewBottom.bounds
alertController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.down;


This fix does not work. The alert is positioned incorrectly over 'viewBottom' and when I click the 'defaultAction' button - it crashes again with the above error message.

I'm sort of at a loss here to fix this. Can anyone give some advice on this? I have tried various ways to use


the UIPopoverPresentationControllerDelegate method
-prepareForPopoverPresentation.'


in my code, but wasn't successful. Any advice appreciated on this. Thanks.

Answer

Replace these lines:

alertController.popoverPresentationController?.sourceView = viewBottom
alertController.popoverPresentationController?.sourceRect = viewBottom.bounds
alertController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.down;

with:

if let button = sender as? UIButton {
    alertController.popoverPresentationController?.sourceView = button
    alertController.popoverPresentationController?.sourceRect = button.bounds
}

You must also property setup the popoverPresentationController of the share sheet in your displayShareSheet method. You should probably pass in the UIButton as a parameter to that method so you can use it there.

Comments