ios UIAlertController 已崩溃 (iPad)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31577140/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 06:58:12  来源:igfitidea点击:

UIAlertController is Crashed (iPad)

iosipaduipopovercontrolleruialertcontrolleruialertsheet

提问by isaced

I am using Xcode 6 to develop an iOS Application.

我正在使用 Xcode 6 开发 iOS 应用程序。

When I used UIAlertController, it can be worked well on iPhone 6 simulator, but crashes on iPad simulator.

当我使用 时UIAlertController,它可以在 iPhone 6 模拟器上运行良好,但在 iPad 模拟器上崩溃。

My problem while clicking "share", then it could be crashed. How could I solve it?

单击“共享”时出现问题,然后它可能会崩溃。我怎么能解决呢?

Here is my Code:

这是我的代码:

override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject] {

    var shareAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Share", handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in

        let shareMenu = UIAlertController(title: nil, message: "Share using", preferredStyle: .ActionSheet)
        let twitterAction = UIAlertAction(title: "Twitter", style: UIAlertActionStyle.Default, handler: nil)
        let facebookAction = UIAlertAction(title: "Facebook", style: UIAlertActionStyle.Default, handler: nil)
        let emailAction = UIAlertAction(title: "Email", style: UIAlertActionStyle.Default, handler: nil)
        let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)

        shareMenu.addAction(twitterAction)
        shareMenu.addAction(facebookAction)
        shareMenu.addAction(emailAction)
        shareMenu.addAction(cancelAction)

        self.presentViewController(shareMenu, animated: true, completion: nil)
        }
    )

Xcode showed this message:

Xcode 显示此消息:

******Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIAlertController (<UIAlertController: 0xaf71c80>) 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[![enter image description here][1]][1] present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.'
*** First throw call stack:
(
    0   CoreFoundation                      0x0023c746 __exceptionPreprocess + 182
    1   libobjc.A.dylib                     0x01c7aa97 objc_exception_throw + 44
    2   UIKit                               0x012c4062 -[UIPopoverPresentationController presentationTransitionWillBegin] + 3086
    3   UIKit                               0x00bda174 __71-[UIPresentationController _initViewHierarchyForPresentationSuperview:]_block_invoke + 1549
    4   UIKit                               0x00bd8247 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke + 198
    5   UIKit                               0x00c0d31b __40+[UIViewController _scheduleTransition:]_block_invoke + 18
    6   UIKit                               0x00ac6862 ___afterCACommitHandler_block_invoke + 15
    7   UIKit                               0x00ac680d _applyBlockToCFArrayCopiedToStack + 415
    8   UIKit                               0x00ac6622 _afterCACommitHandler + 549
    9   CoreFoundation                      0x0015d86e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
    10  CoreFoundation                      0x0015d7b0 __CFRunLoopDoObservers + 400
    11  CoreFoundation                      0x001531ea __CFRunLoopRun + 1226
    12  CoreFoundation                      0x00152a5b CFRunLoopRunSpecific + 443
    13  CoreFoundation                      0x0015288b CFRunLoopRunInMode + 123
    14  GraphicsServices                    0x047b82c9 GSEventRunModal + 192
    15  GraphicsServices                    0x047b8106 GSEventRun + 104
    16  UIKit                               0x00a9c106 UIApplicationMain + 1526
    17  Mars I                              0x0001c724 main + 180
    18  libdyld.dylib                       0x02392ac9 start + 1
    19  ???                                 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException******

回答by Karoly Nyisztor

To keep it device independent, rather use it as shown in the snippet below. This code will return nil for popoverPresentationController on an iPhone / compact size device, so you can safely use it in universal projects.

为了保持设备独立,不如使用它,如下面的代码片段所示。此代码将为 iPhone / 紧凑型设备上的 popoverPresentationController 返回 nil,因此您可以在通用项目中安全地使用它。

if let popoverPresentationController = shareMenu.popoverPresentationController {
    popoverPresentationController.sourceView = self.view
    popoverPresentationController.sourceRect = sender.bounds
}
self.presentViewController(shareMenu, animated: true, completion: nil)

回答by isaced

try this code:

试试这个代码:

shareMenu.popoverPresentationController.sourceView = self.view
shareMenu.popoverPresentationController.sourceRect = CGRectMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0, 1.0, 1.0)

self.presentViewController(shareMenu, animated: true, completion: nil)

回答by kurtanamo

Swift 4

斯威夫特 4

popoverPresentationController.permittedArrowDirections = .init(rawValue: 0)
popoverPresentationController.sourceView = self.view
popoverPresentationController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)

回答by Mayuri R Talaviya

I am also face same issue and finally got the solution. Here is my solution for Objective-C:

我也面临同样的问题,终于得到了解决方案。这是我对 Objective-C 的解决方案:

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Select you option:"
                                                                         message:nil
                                                                  preferredStyle:UIAlertControllerStyleActionSheet];

UIAlertAction *action = [UIAlertAction actionWithTitle:@“share”
                                                     style:UIAlertActionStyleDefault
                                                   handler:^(UIAlertAction *action) {
                                                       // do other things
                                                   }];
[alertController addAction:action];

UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel"
                                                       style:UIAlertActionStyleCancel
                                                     handler:^(UIAlertAction *action) {
                                                     }];
[alertController addAction:cancelAction];

// Remove arrow from action sheet.
[alertController.popoverPresentationController setPermittedArrowDirections:0];

//For set action sheet to middle of view.
CGRect rect = self.view.frame;
rect.origin.x = self.view.frame.size.width / 20;
rect.origin.y = self.view.frame.size.height / 20;
alertController.popoverPresentationController.sourceView = self.view;
alertController.popoverPresentationController.sourceRect = rect;

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

回答by yuelong qin

reference: ActionSheet Popover on iPad in Swift

参考: Swift 中 iPad 上的 ActionSheet Popover

create popoverController :

创建 popoverController :

let alertController = UIAlertController(title: nil, message: "Alert message.", preferredStyle: .actionSheet)
self.present(alertController, animated: true, completion: nil)

if you want show alert with indicator view should:

如果你想用指示器视图显示警报应该:

if let popoverController = alertController.popoverPresentationController {
    popoverController.barButtonItem = sender
}

with indicator

带指示器

show alert in center:

在中心显示警报:

if let popoverController = alertController.popoverPresentationController {
  popoverController.sourceView = self.view
  popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0) 
}

center with indicator

带指示器的中心

center no indicator:

中心无指标:

if let popoverController = alertController.popoverPresentationController {
  popoverController.sourceView = self.view
  popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
  popoverController.permittedArrowDirections = []
}

center no indicator

中心无指示

回答by Jo?e Ws

I use this handy extension to create action sheets that never crash

我使用这个方便的扩展来创建永不崩溃的操作表

extension UIAlertController {

    class func actionSheetWith(title: String?, message: String?, sourceView: UIView?, sourceFrame: CGRect?) -> UIAlertController {
        let actionController = UIAlertController(title: title, message: message, preferredStyle: .actionSheet)
        if actionController.responds(to: #selector(getter: popoverPresentationController)) {
            actionController.popoverPresentationController?.sourceView = sourceView ?? StoryboardHelper.tabBarControllerTopController()?.view
            actionController.popoverPresentationController?.sourceRect = sourceFrame ?? CGRect(x: 0, y: 0, width: 0, height: 0)
        }
        return actionController
    }

}

回答by Genevios

I use this code, very easy and understand, maybe i can help for any

我使用此代码,非常简单易懂,也许我可以帮助任何

//if iPhone
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
        [self presentViewController:actionSheet animated:YES completion:nil];
    }
    //if iPad
    else {
        // Change Rect to position Popover
        UIPopoverController *popup = [[UIPopoverController alloc] initWithContentViewController:actionSheet];
        [popup presentPopoverFromRect:CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height/4, 0, 0)inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    }

回答by sohail059

Swift 3

斯威夫特 3

shareMenu.popoverPresentationController?.sourceView = self.view
shareMenu.popoverPresentationController?.sourceRect = 
    CGRect(x: view.bounds.size.width, 
           y: view.bounds.size.height-80, 
           width: 1.0, height: 1.0)

source rect is the point from were you want to show popover view.

source rect 是您想要显示弹出视图的重点。

回答by Jaydip

for iOS 13

适用于iOS 13

used it.

使用了它。

 if #available(iOS 13.0, *) {
            if let popoverPresentationController = actionSheet.popoverPresentationController {
                popoverPresentationController.sourceView = self.view
                popoverPresentationController.sourceRect = sender.frame
            }
            self.present(actionSheet, animated: true, completion: nil)
        } else {
            actionSheet.popoverPresentationController?.sourceView = self.view
            actionSheet.popoverPresentationController?.sourceRect = sender.frame

            actionSheet.show()
        }

回答by Olexa Boyko

If you don't need presenting the alert as popover, you can simply use UIAlertController.Style.alertas preferred style, when initializing AlertViewController.

如果您不需要将警报显示为弹出框,您可以UIAlertController.Style.alert在初始化AlertViewController.

let shareMenu = UIAlertController(title: nil, message: "Share using", preferredStyle: .alert)