未捕获的异常"NSGenericException:应用程序已呈现样式 UIAlertControllerStyleActionSheet 的 UIAlertControllerStyleAction



我正在开发一个在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 () style UIAlertControllerStyleActionSheet.的模态演示风格 具有这种样式的UIAlertController是UIModalPresentationPopover。你 必须通过警报提供此弹出窗口的位置信息 控制器的弹出框演示控制器。您必须提供 sourceView 和 sourceRect 或 barButtonItem。如果此信息是 当您出示警报控制器时未知,您可以在 UIPopoverPresentationControllerDelegate 方法 -准备弹出演示。

将源视图和源矩形添加到警报控制器。

[[alertController popoverPresentationController] setSourceView:self.view];
[[alertController popoverPresentationController] setSourceRect:CGRectMake(0,0,1,1)];
[[alertController popoverPresentationController] setPermittedArrowDirections:UIPopoverArrowDirectionUp];
[self presentViewController:alertController animated:true completion:nil];

实际上在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
}

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

iPad 上不允许使用 UIPopover,但有一种方法可以做到这一点,正如其他答案所表明的那样。 这是一个 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行替换为以下行之一将控制弹出框在导航栏下方的显示位置。 您还可以将 x 和 y 更改为不同元素的边界或框架中的正确值(如果您的控件位于 iPad 上的导航栏下方)。

左上角

let xOrigin = 0

顶部中间

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

右上

let xOrigin = self.view.bounds.width

希望这有帮助。

最新更新