UIAlertController and UIPopoverController in a Universal App?
Asked Answered
L

1

6

I am working on a universal app for the iPhone 6S / 6S Plus / and iPad form factors. Normally, presenting actionsheets / alertviews on an iPhone-only app is a simple manner. But my application crashes when I attempt to present these on an iPad, returning the following error:

"Terminating app due to uncaught exception '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.'"

It is my understanding that I must display a popover when the application is running on an iPad instead of a conventional actionsheet. For the sake of context, the action sheet is presented by a button in a custom cell, which is in a tableview.

What is the best way to handle UIAlertControllers / Action Sheets / UIPopoverControllers in a universal app?

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    [tableView deselectRowAtIndexPath:indexPath animated:YES];

    NSString *titleToUse = @"";

//    switch (self.openGroup) {
//        case 0:
//            titleToUse = [self.deviceListData[indexPath.row] valueForKey:@"deviceName"];
//            break;
//            
//        case 1:
//            titleToUse = [self.computersData[indexPath.row] valueForKey:@"deviceName"];
//            break;
//            
//        case 2:
//            titleToUse = [self.mobileData[indexPath.row] valueForKey:@"deviceName"];
//            break;
//            
//        case 3:
//            titleToUse = [self.smartData[indexPath.row] valueForKey:@"deviceName"];
//            break;
//            
//        default:
//            break;
//    }

    UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:titleToUse message:nil preferredStyle:UIAlertControllerStyleActionSheet];

    [actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {

        // Cancel button tappped.

    }]];

    [actionSheet addAction:[UIAlertAction actionWithTitle:@"Get More Info" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {

        AlertDetailModal *alertDetail = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"alertDetailModal"];

        alertDetail.delegate = self;
        alertDetail.securityLevel = self.securityLevel;

        UINavigationController *modalNavCon = [[UINavigationController alloc] initWithRootViewController:alertDetail];
        [self presentViewController:modalNavCon animated:YES completion:nil];

    }]];

    [actionSheet addAction:[UIAlertAction actionWithTitle:@"Bandwidth Profile" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {

    }]];

    [actionSheet addAction:[UIAlertAction actionWithTitle:@"Alert Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {

    }]];

    [actionSheet addAction:[UIAlertAction actionWithTitle:@"Security Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {

    }]];

    [actionSheet addAction:[UIAlertAction actionWithTitle:@"Unblock Connection" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {

    }]];

    // Present action sheet.
    [self presentViewController:actionSheet animated:YES completion:nil];

}
Lanner answered 29/4, 2016 at 20:52 Comment(0)
V
21

The fact that its universal is irrelevant. You setup the alert controller's popoverPresentationController the same regardless. It will then display properly on all devices.

In this case you should set the sourceView to tableView and sourceRect to the rect for the selected row.

UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:titleToUse message:nil preferredStyle:UIAlertControllerStyleActionSheet];
actionSheet.popoverPresentationController.sourceView = tableView;
actionSheet.popoverPresentationController.sourceRect = [tableView rectForRowAtIndexPath:indexPath];
Vannessavanni answered 29/4, 2016 at 20:56 Comment(1)
Perfect! Thank you very much, very concise and clear answer :)Lanner

© 2022 - 2024 — McMap. All rights reserved.