未捕获的异常 'NSGenericException: 应用程序提供了一个 UIAlertController 样式的 UIAlertControllerStyleActionSheet

Posted

技术标签:

【中文标题】未捕获的异常 \'NSGenericException: 应用程序提供了一个 UIAlertController 样式的 UIAlertControllerStyleActionSheet【英文标题】:uncaught exception 'NSGenericException: application has presented a UIAlertController of style UIAlertControllerStyleActionSheet未捕获的异常 'NSGenericException: 应用程序提供了一个 UIAlertController 样式的 UIAlertControllerStyleActionSheet 【发布时间】:2018-09-21 06:51:32 【问题描述】:

我正在开发一个在 iPhone 上运行的应用程序运行良好,但是当我尝试在 iPad 上运行时它崩溃了

这是我的代码:

- (void)parseCountryStates:(NSDictionary *)json
    
    countryPickerView.hidden = TRUE;
    NSDictionary *listing = [json objectForKey:@"country"];
    countryArray = [listing allValues];
    countryIDArray = [listing allKeys];

    [countryPickerView reloadAllComponents];
    alertController = [UIAlertController
                       alertControllerWithTitle:@"Select Service Type"
                       message:nil
                       preferredStyle:UIAlertControllerStyleActionSheet];
    int count = (int)[countryPickerView numberOfRowsInComponent:0];

    for (int i = 0; i < count; i++)
    
        UIAlertAction* button = [UIAlertAction
                                 actionWithTitle:[[countryPickerView delegate] pickerView:countryPickerView titleForRow:i forComponent:0]
                                 style:UIAlertActionStyleDefault
                                 handler:^(UIAlertAction * action)
                                 
                                     countryField.text = [action title];
                                     countryStr = countryField.text;
                                     if ([countryArray containsObject:countryStr]) 
                                         countryidStr = [countryIDArray objectAtIndex:[countryArray indexOfObject:countryStr]];
                                         NSLog(@"CountryidStr %@",countryidStr);
                                         [self getState];
                                     
                                 ];
        [alertController addAction:button];

    

    UIAlertAction* cancel = [UIAlertAction
                             actionWithTitle:@"Cancel"
                             style:UIAlertActionStyleCancel
                             handler:^(UIAlertAction * action)
                             
                                 //  UIAlertController will automatically dismiss the view
                             ];
    [alertController addAction:cancel];
    [self presentViewController:alertController animated:true completion:nil];

我正在分享它的崩溃日志

*** 由于未捕获的异常“NSGenericException”而终止应用程序,原因:“您的应用程序已提交了一个 UIAlertController () 样式 UIAlertControllerStyleActionSheet。 modalPresentationStyle 的 具有这种风格的 UIAlertController 是 UIModalPresentationPopover。你 必须通过警报提供此弹出窗口的位置信息 控制器的 popoverPresentationController。您必须提供 sourceView 和 sourceRect 或 barButtonItem。如果这个信息是 当您呈现警报控制器时不知道,您可以在 UIPopoverPresentationControllerDelegate 方法 -prepareForPopoverPresentation。

【问题讨论】:

ipad 不支持 Actionsheet 你必须把它显示为 popover 控制器太多类似的问题找到它 ActionSheet not working iPad的可能重复 改为将其标记为重复请回答 请搜索而不是询问 【参考方案1】:

将源视图和源矩形添加到您的 alertController。

[[alertController popoverPresentationController] setSourceView:self.view];
[[alertController popoverPresentationController] setSourceRect:CGRectMake(0,0,1,1)];
[[alertController popoverPresentationController] setPermittedArrowDirections:UIPopoverArrowDirectionUp];

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

【讨论】:

【参考方案2】:

实际上 ipad 上的警报控制器是不允许的,您可以使用弹出框来显示某种警报

以编程方式

UIViewController *newViewCont = [[UIViewController  alloc] init];
newViewCont.view = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 180, 180)];
newViewCont.modalPresentationStyle = UIModalPresentationPopover;

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

UIPopoverPresentationController *pop = [newViewCont popoverPresentationController];
pop.permittedArrowDirections = UIPopoverArrowDirectionAny;

[pop setSourceView:myButton];
[pop setSourceRect:myButton.bounds];

使用故事板

// grab the view controller we want to show
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *controller = [storyboard instantiateViewControllerWithIdentifier:@"Pop"];

// present the controller
// on iPad, this will be a Popover
// on iPhone, this will be an action sheet
controller.modalPresentationStyle = UIModalPresentationPopover;
[self presentViewController:controller animated:YES completion:nil];

// configure the Popover presentation controller
UIPopoverPresentationController *popController = [controller popoverPresentationController];
popController.permittedArrowDirections = UIPopoverArrowDirectionUp;
popController.delegate = self;

// in case we don't have a bar button as reference
popController.sourceView = self.view;
popController.sourceRect = CGRectMake(30, 50, 10, 10);

关闭弹出框

[self dismissViewControllerAnimated:YES completion:nil];

有一个称为 UIPopoverPresentationControllerDelegate 的新协议,它在由于旋转或界面更改而导致的解雇和位置更改时被调用。如果我们愿意,我们甚至可以防止 Popover 被解雇。以下是我们可以实现的三种方法:

- (void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController 

// called when a Popover is dismissed


- (BOOL)popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController 

// return YES if the Popover should be dismissed
// return NO if the Popover should not be dismissed
return YES;


- (void)popoverPresentationController:(UIPopoverPresentationController *)popoverPresentationController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView *__autoreleasing  _Nonnull *)view 

// called when the Popover changes position

不要忘记遵守协议,并将委托设置为您的反应类。

【讨论】:

【参考方案3】:

UIPopovers 不允许在 iPad 上使用,但正如其他答案所表明的那样,您可以通过一种方法来执行此操作。这是 Swift 5.x 版本。

let ac = UIAlertController(title: "Some title goes here", message: nil, preferredStyle: .actionSheet)

ac.addAction(UIAlertAction(title: "Some button name", style: .default) 
        [unowned self] _ in
        // stuff to do goes here
        self.doSomething()
    )

// iPad specific code
ac.popoverPresentationController?.sourceView = self.view
let xOrigin = nil // Replace this with one of the lines at the end
let popoverRect = CGRect(x: xOrigin, y: 0, width: 1, height: 1)
ac.popoverPresentationController?.sourceRect = popoverRect
ac.popoverPresentationController?.permittedArrowDirections = .up

present(ac, animated: true)

let xOrigin = nil 行替换为以下行之一将控制弹出框出现在导航栏下方的位置。如果您在 iPad 上的导航栏下方有控件,您还可以在不同元素的边界或框架中将 x 和 y 更改为适当的值。

左上角

 let xOrigin = 0

顶部中间

let xOrigin = self.view.bounds.width / 2

右上角

let xOrigin = self.view.bounds.width

希望这会有所帮助。

【讨论】:

以上是关于未捕获的异常 'NSGenericException: 应用程序提供了一个 UIAlertController 样式的 UIAlertControllerStyleActionSheet的主要内容,如果未能解决你的问题,请参考以下文章

未捕获异常的角度中断/暂停

Android视图:未捕获的处理程序:线程主因未捕获的异常而退出

捕获未处理的异常

如何在 Promise 的回调中捕获未捕获的异常

未捕获 Java 异常

捕获块未捕获异常