I have this code sitting in a UIVIewController (XCode 6.1, iOS 8.1.1):
[UIAlertController showActionSheetInViewController:self
withTitle:@"Test Action Sheet"
message:NSLocalizedString(@"Are you sure you want to delete ALL appointments?",nil)
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:@"Yes"
otherButtonTitles:@[@"No"] // same as Cancel
tapBlock:^(UIAlertController *controller, UIAlertAction *action, NSInteger buttonIndex){
if (buttonIndex == UIAlertControllerBlocksCancelButtonIndex) {
NSLog(@"Cancel Tapped");
} else if (buttonIndex == UIAlertControllerBlocksDestructiveButtonIndex) {
NSLog(@"Delete Tapped");
} else if (buttonIndex >= UIAlertControllerBlocksFirstOtherButtonIndex) {
NSLog(@"Other Action Index %ld", (long)buttonIndex - UIAlertControllerBlocksFirstOtherButtonIndex);
}
}];
When I run it, I get this run-time error:
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIAlertController (<UIAlertController: 0x7fdfe3324f00>) 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 do I need to do to make this work? (I have looked at SO and Google and found nothing specific). I appreciate any help I can get on this...
UPDATE I re-wrote it without the 3rd-party code; added this code, and now it works!
UIAlertController * view= [UIAlertController
alertControllerWithTitle:@"My Title"
message:@"Select your Choice"
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction* ok = [UIAlertAction
actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
//Do some thing here
[view dismissViewControllerAnimated:YES completion:nil];
}];
UIAlertAction* cancel = [UIAlertAction
actionWithTitle:@"Cancel"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[view dismissViewControllerAnimated:YES completion:nil];
}];
[view addAction:ok];
[view addAction:cancel];
view.popoverPresentationController.sourceView = self.view;
view.popoverPresentationController.sourceRect = CGRectMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0, 1.0, 1.0);
[self presentViewController: view animated:YES completion:nil];
The error message you received appeared because you ran iPhone code on an iPad. For use on an iPad, you have to set the alertController's popoverPresentationController. The source rectangle can be generated without the sloppy dimension calculations, too. Below, is a complete method, showing how you would encounter the code upon pressing a button. After setting up the AlertController the way you want, you get its popoverPresentationController and set it up for use with the iPad. In the method below, the button what was pressed is the sender. So we cast the sender back to that button, then use the button to set the rectangle. No messy dimensions need calculating. Now, if you run the code on the iPad, the popover will not display the Cancel button, (which does appear on the iPhone). That is by design. If you view the Apple UIPopoverController documentation, you see that the popover is cancelled by tapping outside of it.
- (IBAction)showImagePickerButtonTapped:(id)sender;
{
BOOL isCameraAvailable = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
BOOL isPhotoLibraryAvailable = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary];
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
if (isCameraAvailable) {
[alertController addAction:[UIAlertAction actionWithTitle:@"Camera" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[self _showImagePickerWithSourceType:UIImagePickerControllerSourceTypeCamera];
}]];
}
if (isPhotoLibraryAvailable) {
[alertController addAction:[UIAlertAction actionWithTitle:@"Photo Library" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[self _showImagePickerWithSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
}]];
}
// The following lines are needed for use with the iPad.
UIPopoverPresentationController *alertPopoverPresentationController = alertController.popoverPresentationController;
UIButton *imagePickerButton = (UIButton*)sender;
alertPopoverPresentationController.sourceRect = imagePickerButton.frame;
alertPopoverPresentationController.sourceView = self.view;
[self showDetailViewController:alertController sender:sender];
}
There's precious little information to go on here...
It appears you're using https://github.com/ryanmaxwell/UIAlertController-Blocks, not the standard UIAlertController, in which case the exception suggests changes that the version of the code you're using doesn't cover yet or a use case that requires extra work on your part.
I've never used this 3rd-party code but a quick check doesn't show any obvious "do this" in the docs. My initial recommendation would be to implement the delegate method on the view in question and give it what it wants - the location at which to present the popover.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With