Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIAlertController and UIPopoverController in a Universal App?

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];

}
like image 404
arcade16 Avatar asked Apr 29 '16 20:04

arcade16


1 Answers

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];
like image 177
rmaddy Avatar answered Nov 13 '22 20:11

rmaddy