在 iOS 8.0 中,Apple 引入了 UIAlertController 来替换 UIActionSheet。不幸的是,Apple 没有添加任何关于如何呈现它的信息。我在 hayaGeek 的博客上找到了关于它的 entry,但是,它似乎不适用于 iPad。观点完全错位了:
https://i.stack.imgur.com/KhAaj.png
https://i.stack.imgur.com/lFd3S.png
我使用以下代码在界面上显示它:
let alert = UIAlertController()
// setting buttons
self.presentModalViewController(alert, animated: true)
有没有其他方法可以为 iPad 添加它?还是 Apple 只是忘记了 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 显示为弹出框,它要求您使用 sourceView 和 sourceRect 或 barButtonItem 为弹出框的呈现指定一个锚点
barButtonItem
源视图
源矩形
为了指定锚点,您需要获取对 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)
}
如果您不设置演示者,您将在 -[UIPopoverPresentationController presentationTransitionWillBegin]
中在 iPad 上遇到异常,并显示以下消息:
致命异常:NSGenericException 您的应用程序出现了 UIAlertController (
斯威夫特 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.pad”检查
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")
}
斯威夫特 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)
2018 更新
由于这个原因,我刚刚拒绝了一个应用程序,一个非常快速的解决方案就是从使用操作表更改为警报。
发挥了魅力并顺利通过了 App Store 测试人员。
可能不是适合每个人的答案,但我希望这可以帮助你们中的一些人快速摆脱困境。
Swift 4.2 你可以使用这样的条件:
let alert = UIAlertController(title: nil, message: nil, preferredStyle: UIDevice.current.userInterfaceIdiom == .pad ? .alert : .actionSheet)
这是一个快速的解决方案:
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];
对我来说,我只需要添加以下内容:
if let popoverController = alertController.popoverPresentationController {
popoverController.barButtonItem = navigationItem.rightBarButtonItem
}
斯威夫特 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 = []
只需在展示您的操作表之前添加以下代码:
if let popoverController = optionMenu.popoverPresentationController {
popoverController.sourceView = self.view
popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
popoverController.permittedArrowDirections = []
}
它适用于 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(_ viewControllerToPresent:animated:completion:)
:
呈现具有 .alert 的首选样式的 UIAlertController
使用 .modalPresentationStyle 呈现 UIViewController: .overFullScreen .formSheet .automatic 如果未指定 modalPresentationStyle 的默认值 .currentContext .fullScreen .custom .overCurrentContext
.overFullScreen
.formSheet
.automatic modalPresentationStyle 未指定时的默认值
.currentContext
。全屏
。风俗
.overCurrentContext
在演示之前配置 popoverPresentationController
的 sourceRect
和 sourceView
:
使用 .actionSheet 的首选样式呈现 UIAlertController
使用 .modalPresentationStyle 呈现 UIViewController:.popover .none 这将在 iPhone 和 iPad 上崩溃,并出现错误“指定的模态呈现样式没有相应的呈现控制器”。
.popover
.none 这将在 iPhone 和 iPad 上崩溃,并出现错误“指定的模态演示样式没有相应的演示控制器”。
呈现 UIActivityViewController(基于 https://developer.apple.com/documentation/uikit/uiactivityviewcontroller ;“在 iPad 上,您必须在弹出窗口中呈现视图控制器。在 iPhone 和 iPod touch 上,您必须以模态方式呈现它。”)
这是配置 popoverPresentationController
的示例
if let popoverController = popoverPresentationController {
popoverController.sourceView = view
popoverController.sourceRect = CGRect(x: view.bounds.maxX, y: 40, width: 0, height: 0)
}
如果您发现此处未列出的任何其他案例,请告诉我!
不定期副业成功案例分享