Правильное представление UIAlertController на iPad с помощью iOS 8

С iOS 8.0, Apple представила UIAlertController заменить UIActionSheet. К сожалению, Apple не добавила никакой информации о том, как ее представить. Я нашел запись об этом в блоге hayaGeek, однако, он, похоже, не работает на iPad. Вид совершенно неуместен:

неуместны: Misplaced image

исправить: enter image description here

Я использую следующий код, чтобы показать его по интерфейсу:

    let alert = UIAlertController()
    // setting buttons
    self.presentModalViewController(alert, animated: true)

Is есть другой способ добавить его для iPad? Или Apple просто забыла iPad или еще не реализовала его?

6 ответов


вы можете представить UIAlertController из popover с помощью UIPopoverPresentationController.

В Obj-C:

UIViewController *self; // code assumes you're in a view controller
UIButton *button; // the button you want to show the popup sheet from

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

на iPad предупреждение будет отображаться как popover с помощью нового UIPopoverPresentationController, требуется указать точку привязки для представления popover с помощью sourceView и sourceRect или barButtonItem

  • barButtonItem
  • sourceView
  • sourceRect

чтобы указать точку привязки, вам нужно будет получить ссылку на UIAlertController UIPopoverPresentationController и установите одно из свойств следующим образом:

alertController.popoverPresentationController.barButtonItem = button;

пример кода:

UIAlertAction *actionDelete = nil;
UIAlertAction *actionCancel = nil;

// create action sheet
UIAlertController *alertController = [UIAlertController
                                      alertControllerWithTitle:actionTitle message:nil
                                      preferredStyle:UIAlertControllerStyleActionSheet];

// Delete Button
actionDelete = [UIAlertAction
                actionWithTitle:NSLocalizedString(@"IDS_LABEL_DELETE", nil)
                style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {

                    // Delete
                    // [self deleteFileAtCurrentIndexPath];
                }];

// Cancel Button
actionCancel = [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 sheet
alertController.popoverPresentationController.barButtonItem = button;
alertController.popoverPresentationController.sourceView = self.view;

[self presentViewController:alertController animated:YES
                 completion:nil];

в Swift 2, вы хотите сделать что-то вроде этого, чтобы правильно показать его на iPhone и 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)
}

Если вы не установите ведущего, вы получите исключение на iPad в -[UIPopoverPresentationController presentationTransitionWillBegin] появляется следующее сообщение:

Фатальное Исключение: NSGenericException Ваше приложение представило UIAlertController () стиля UIAlertControllerStyleActionSheet. ModalPresentationStyle UIAlertController с этим стилем является UIModalPresentationPopover. Вы должны предоставить информацию о местоположении для этого popover через popoverPresentationController контроллера оповещения. Необходимо предоставить либо sourceView и sourceRect или barButtonItem. Если эта информация не известна при представлении контроллера оповещений, ее можно указать в методе UIPopoverPresentationControllerDelegate-prepareForPopoverPresentation.


обновление для Swift 3.0 и выше

    let actionSheetController: UIAlertController = UIAlertController(title: "SomeTitle", message: nil, preferredStyle: .actionSheet)

    let editAction: UIAlertAction = UIAlertAction(title: "Edit Details", style: .default) { action -> Void in

        print("Edit Details")
    }

    let deleteAction: UIAlertAction = UIAlertAction(title: "Delete Item", style: .default) { action -> Void in

        print("Delete Item")
    }

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

    actionSheetController.addAction(editAction)
    actionSheetController.addAction(deleteAction)
    actionSheetController.addAction(cancelAction)

//        present(actionSheetController, animated: true, completion: nil)   // doesn't work for iPad

    actionSheetController.popoverPresentationController?.sourceView = yourSourceViewName // works for both iPhone & iPad

    present(actionSheetController, animated: true) {
        print("option menu presented")
    }

вот быстрое решение:

NSString *text = self.contentTextView.text;
NSArray *items = @[text];

UIActivityViewController *activity = [[UIActivityViewController alloc]
                                      initWithActivityItems:items
                                      applicationActivities:nil];

activity.excludedActivityTypes = @[UIActivityTypePostToWeibo];

if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
    //activity.popoverPresentationController.sourceView = shareButtonBarItem;

    activity.popoverPresentationController.barButtonItem = shareButtonBarItem;

    [self presentViewController:activity animated:YES completion:nil];

}
[self presentViewController:activity animated:YES completion:nil];

обновить 2018

У меня просто было приложение отклонено по этой причине, и очень быстрое разрешение было просто изменить с помощью листа действий на предупреждение.

работал шарм и прошел тестеры App Store просто отлично.

может не быть подходящим ответом для всех, но я надеюсь, что это поможет некоторым из вас из рассола быстро.