在iOS 8.0中,苹果引入了UIAlertController来取代UIActionSheet。不幸的是,苹果没有提供任何关于如何展示的信息。我在hayaGeek的博客上找到了一个关于它的条目,然而,它似乎不能在iPad上运行。这种观点是完全错误的:

错误的:

正确的:

我使用以下代码在界面上显示它:

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

是否有其他方法添加到iPad上?或者苹果只是忘记了iPad,或者还没有推出iPad ?


当前回答

对我来说,我只需要添加以下内容:

if let popoverController = alertController.popoverPresentationController {
    popoverController.barButtonItem = navigationItem.rightBarButtonItem
}

其他回答

2018年更新

我刚刚因为这个原因拒绝了一款应用,而我的一个快速解决方法便是将操作表单改为提醒。

很有魅力,顺利通过了App Store测试。

可能不是每个人都适合这个答案,但我希望这能帮助你们中的一些人迅速摆脱困境。

斯威夫特4.2 你可以像这样使用condition:

let alert = UIAlertController(title: nil, message: nil, preferredStyle: UIDevice.current.userInterfaceIdiom == .pad ? .alert : .actionSheet)

Swift 4及以上

我已经创建了一个扩展

extension UIViewController {
  public func addActionSheetForiPad(actionSheet: UIAlertController) {
    if let popoverPresentationController = actionSheet.popoverPresentationController {
      popoverPresentationController.sourceView = self.view
      popoverPresentationController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
      popoverPresentationController.permittedArrowDirections = []
    }
  }
}

使用方法:

let actionSheetVC = UIAlertController(title: "Title", message: nil, preferredStyle: .actionSheet)
addActionSheetForiPad(actionSheet: actionSheetVC)
present(actionSheetVC, animated: true, completion: nil)

斯威夫特5

适用于iPad和iPhone。

动作表下方悬停一个按钮

对于iPhone,动作表将显示正常,iPad将显示在按钮下方。

actionSheet.popoverPresentationController?.sourceView = fooButton
actionSheet.popoverPresentationController?.sourceRect = fooButton.bounds

动作表在屏幕/视图的中间

对于iPhone,动作表将正常显示,iPad将显示在屏幕/视图的中间。

actionSheet.popoverPresentationController?.sourceView = view
actionSheet.popoverPresentationController?.sourceRect = CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 0, height: 0)
actionSheet.popoverPresentationController?.permittedArrowDirections = []

在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],并显示以下消息:

Fatal Exception: NSGenericException Your application has presented a UIAlertController (<UIAlertController: 0x17858a00>) 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.