【问题标题】:UIAlertController is Crashed (iPad)UIAlertController 崩溃 (iPad)
【发布时间】:2015-10-13 03:43:42
【问题描述】:

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

当我使用UIAlertController时,它在iPhone 6模拟器上可以正常工作,但在iPad模拟器上崩溃。

我在点击“分享”时出现问题,然后它可能会崩溃。 我该如何解决?

这是我的代码:

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 显示此消息:

******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******

【问题讨论】:

  • Apple 表示,如果您想呈现任何视图控制器,并且其类型的 AlertViewController 然后出现在弹出窗口中而不是独立视图中,这与用户体验有关。

标签: ios ipad uipopovercontroller uialertcontroller uialertsheet


【解决方案1】:

我发现这个链接很有用,对我有用

https://medium.com/@nickmeehan/actionsheet-popover-on-ipad-in-swift-5768dfa82094

进行如下细微更改以调整对齐方式。

if let popoverPresentationController = alert.popoverPresentationController {
        popoverPresentationController.sourceView = self.view
        popoverPresentationController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.size.height * 0.85, width: 0, height: 0)
        popoverPresentationController.permittedArrowDirections = []
    }

【讨论】:

    【解决方案2】:

    如果您不需要将警报显示为弹出框,则可以在初始化 AlertViewController 时简单地使用 UIAlertController.Style.alert 作为首选样式。

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

    【讨论】:

      【解决方案3】:

      适用于 iOS 13

      用过。

       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()
              }
      

      【讨论】:

        【解决方案4】:

        我也面临同样的问题,终于得到了解决方案。 这是我对 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];
        

        【讨论】:

        • 很好奇为什么我们在这里除以 20。我尝试了 2.0 并将其放在右下角。关于几何的一些东西还不清楚。
        • Swift 4 用于删除箭头:popoverPresentationController.permittedArrowDirections = .init(rawValue: 0)
        【解决方案5】:

        斯威夫特 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)
        

        【讨论】:

          【解决方案6】:

          reference: ActionSheet Popover on iPad in Swift

          创建 popoverController :

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

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

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

          with 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) 
          }
          

          center with 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

          【讨论】:

            【解决方案7】:

            斯威夫特 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)
            

            源矩形是您想要显示弹出视图的起点。

            【讨论】:

              【解决方案8】:

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

              //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];
                  }
              

              【讨论】:

                【解决方案9】:

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

                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
                    }
                
                }
                

                【讨论】:

                  【解决方案10】:

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

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

                  【讨论】:

                  • 刚刚在iOS10上遇到这个问题,不认为它已修复
                  • 实际上,您不需要执行if let 检查,就像popoverPresentationControllernil 一样不会设置任何内容。
                  • .sourceView 应该是发件人,而不是 self.view 以显示正确的箭头方向
                  • 在这种情况下,sender 到底是什么?是执行操作的视图吗?
                  • 是的,发送者是触发动作的 UIControl 或 UIView。
                  【解决方案11】:

                  试试这个代码:

                  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)
                  

                  【讨论】:

                  • 你能解释一下CGRectMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0, 1.0, 1.0)吗?
                  • @CerlinBoss 这在视图中间定义了一个 1 像素的正方形,用于指示菜单箭头应指向的位置。
                  猜你喜欢
                  • 2017-02-20
                  • 1970-01-01
                  • 2017-03-24
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-05-14
                  • 1970-01-01
                  • 2012-11-26
                  • 1970-01-01
                  相关资源
                  最近更新 更多