在iOS 8.0中,苹果引入了UIAlertController来取代UIActionSheet。不幸的是,苹果没有提供任何关于如何展示的信息。我在hayaGeek的博客上找到了一个关于它的条目,然而,它似乎不能在iPad上运行。这种观点是完全错误的:
错误的:
正确的:
我使用以下代码在界面上显示它:
let alert = UIAlertController()
// setting buttons
self.presentModalViewController(alert, animated: true)
是否有其他方法添加到iPad上?或者苹果只是忘记了iPad,或者还没有推出iPad ?
你可以通过使用UIPopoverPresentationController从弹窗中呈现一个UIAlertController。
在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];
Swift 4.2的编辑,虽然有很多博客可用,但它可以节省你的时间去搜索他们。
if let popoverController = yourAlert.popoverPresentationController {
popoverController.sourceView = self.view //to set the source of your alert
popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0) // you can set this as per your requirement.
popoverController.permittedArrowDirections = [] //to hide the arrow of any particular direction
}
在iPad上,警报将使用新的UIPopoverPresentationController以弹出窗口的形式显示,它要求你为弹出窗口的显示指定一个锚点,使用:
或者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],并显示以下消息:
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.
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")
}
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
我在iPhone上使用“actionsheet”样式,在iPad上使用“alert”样式。iPad显示在屏幕中央。不需要指定sourceView或将视图锚定在任何位置。
var alertStyle = UIAlertController.Style.actionSheet
if (UIDevice.current.userInterfaceIdiom == .pad) {
alertStyle = UIAlertController.Style.alert
}
let alertController = UIAlertController(title: "Your title", message: nil, preferredStyle: alertStyle)
编辑:根据ShareToD的建议,更新了已弃用的“UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.”垫“检查
它将同时适用于iphone和ipad
func showImagePicker() {
var alertStyle = UIAlertController.Style.actionSheet
if (UIDevice.current.userInterfaceIdiom == .pad) {
alertStyle = UIAlertController.Style.alert
}
let alert = UIAlertController(title: "", message: "Upload Attachment", preferredStyle: alertStyle)
alert.addAction(UIAlertAction(title: "Choose from gallery", style: .default , handler:{ (UIAlertAction) in
self.pickPhoto(sourceType: .photoLibrary)
}))
alert.addAction(UIAlertAction(title: "Take Photo", style: .default, handler:{ (UIAlertAction) in
self.pickPhoto(sourceType: .camera)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler:{ (UIAlertAction) in
}))
present(alert, animated: true, completion: nil)
}
如果您的代码库同时支持iPhone和iPad设备,请考虑以下内容
在以下情况下定期使用present(_ viewcontrollertoppresent:animated:completion:)
呈现一个preferredStyle为.alert的UIAlertController
用.modalPresentationStyle表示一个UIViewController:
.overFullScreen
.formSheet
.automatic未指定modalPresentationStyle时的默认值
.currentContext
.fullScreen
.custom
.overCurrentContext
在呈现前配置popoverPresentationController的sourceRect和sourceView:
Presenting a UIAlertController with preferredStyle of .actionSheet
Presenting a UIViewController with .modalPresentationStyle of:
.popover
.none This will crash on both iPhone and iPads with the error "The specified modal presentation style doesn't have a corresponding presentation controller."
Presenting a UIActivityViewController (Based on https://developer.apple.com/documentation/uikit/uiactivityviewcontroller ; "On iPad, you must present the view controller in a popover. On iPhone and iPod touch, you must present it modally.")
下面是一个配置popoverPresentationController的例子
if let popoverController = popoverPresentationController {
popoverController.sourceView = view
popoverController.sourceRect = CGRect(x: view.bounds.maxX, y: 40, width: 0, height: 0)
}
如果你发现这里没有列出的其他案例,请告诉我!
斯威夫特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 = []