使用 iOS 8 在 iPad 上正确呈现 UIAlertController
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24224916/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Presenting a UIAlertController properly on an iPad using iOS 8
提问by Matt3o12
With iOS 8.0, Apple introduced UIAlertControllerto replace UIActionSheet. Unfortunately, Apple didn't add any information on how to present it. I found an entryabout it on hayaGeek's blog, however, it doesn't seem to work on iPad. The view is totally misplaced:
在 iOS 8.0 中,Apple 引入了UIAlertController来替换UIActionSheet。不幸的是,Apple 没有添加任何有关如何呈现它的信息。我在 hayaGeek 的博客上找到了有关它的条目,但是,它似乎不适用于 iPad。该视图完全放错了位置:
Misplaced:
错位:
Correct:
正确的:
I use the following code to show it on the interface:
我使用以下代码在界面上显示它:
let alert = UIAlertController()
// setting buttons
self.presentModalViewController(alert, animated: true)
Is there another way to add it for iPad? Or did Apple just forget the iPad, or not implemented, yet?
有没有其他方法可以为 iPad 添加它?或者苹果只是忘记了 iPad,或者还没有实现?
回答by Peter Hajas
You can present a UIAlertController
from a popover by using UIPopoverPresentationController
.
您可以UIAlertController
使用UIPopoverPresentationController
.
In Obj-C:
在 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];
Editing for Swift 4.2, though there are many blogs available for the same but it may save your time to go and search for them.
为 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
}
回答by Sabareesh
On iPad the alert will be displayed as a popover using the new UIPopoverPresentationController, it requires that you specify an anchor point for the presentation of the popover using either a sourceView and sourceRect or a barButtonItem
在 iPad 上,警报将使用新的UIPopoverPresentationController显示为弹出框,它要求您使用 sourceView 和 sourceRect 或 barButtonItem 为弹出框的呈现指定一个锚点
- barButtonItem
- sourceView
- sourceRect
- 条形按钮项
- 源视图
- 源矩形
In order to specify the anchor point you will need to obtain a reference to the UIAlertController's UIPopoverPresentationController and set one of the properties as follows:
为了指定锚点,您需要获取对 UIAlertController 的 UIPopoverPresentationController 的引用,并设置如下属性之一:
alertController.popoverPresentationController.barButtonItem = button;
sample code:
示例代码:
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];
回答by kviksilver
In Swift 2, you want to do something like this to properly show it on iPhone and iPad:
在 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)
}
If you don't set the presenter, you will end up with an exception on iPad in -[UIPopoverPresentationController presentationTransitionWillBegin]
with the following message:
如果您不设置演示者,您将在 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.
致命异常:NSGenericException 您的应用程序提供了 UIAlertControllerStyleActionSheet 样式的 UIAlertController (<UIAlertController: 0x17858a00>)。具有此样式的 UIAlertController 的 modalPresentationStyle 是 UIModalPresentationPopover。您必须通过警报控制器的 popoverPresentationController 提供此弹出框的位置信息。您必须提供 sourceView 和 sourceRect 或 barButtonItem。如果您在呈现警报控制器时不知道此信息,您可以在 UIPopoverPresentationControllerDelegate 方法 -prepareForPopoverPresentation 中提供它。
回答by iAj
Update for Swift 3.0 and higher
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")
}
回答by SongBox
2018 Update
2018 更新
I just had an app rejected for this reason and a very quick resolution was simply to change from using an action sheet to an alert.
我刚刚因为这个原因拒绝了一个应用程序,一个非常快速的解决方案就是从使用操作表更改为警报。
Worked a charm and passed the App Store testers just fine.
很有魅力,并通过了 App Store 测试人员。
May not be a suitable answer for everyone but I hope this helps some of you out of a pickle quickly.
可能不是每个人的合适答案,但我希望这可以帮助你们中的一些人快速摆脱困境。
回答by Siddhesh Mahadeshwar
Swift 4 and above
Swift 4 及以上
I have created an extension
我创建了一个扩展
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 = []
}
}
}
How to use:
如何使用:
let actionSheetVC = UIAlertController(title: "Title", message: nil, preferredStyle: .actionSheet)
addActionSheetForIpad(actionSheet: actionSheetVC)
present(actionSheetVC, animated: true, completion: nil)
回答by Serge Gerasimenko
Here's a quick solution:
这是一个快速的解决方案:
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];
回答by Greg T
Swift 5
斯威夫特 5
I used "actionsheet" style for iPhone and "alert" for iPad. iPad displays in the center of the screen. No need to specify sourceView or anchor the view anywhere.
我在 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)
Edit: Per ShareToD's suggestion, updated deprecated "UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad" check
编辑:根据 ShareToD 的建议,更新已弃用的“UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad”检查
回答by Caption Newt
Just add the following code before presenting your action sheet:
只需在展示您的操作表之前添加以下代码:
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 = []
}
回答by Matthew Becker
For me I just needed to add the following:
对我来说,我只需要添加以下内容:
if let popoverController = alertController.popoverPresentationController {
popoverController.barButtonItem = navigationItem.rightBarButtonItem
}