iOS弹出窗口显示两次会崩溃
iOS popover show twice will crash
我正在使用 objective-c 写关于 UIAlertcontroller
的 UIAlertControllerStyleActionSheet
。
我想在 iPhone 上显示警报 sheet,在 iPad 上显示 popoverPresentationController
。
首先,我设置了 UIPopoverPresentationControllerDelegate
委托。
当我点击我的按钮时,弹出窗口显示正确。
但是我在屏幕上单击关闭了弹出窗口。它会显示下面的警告。
[Warning] <_UIPopoverBackgroundVisualEffectView 0x14be52ef0> is being asked to animate its opacity. This will cause the effect to appear broken until opacity returns to 1.
现在当我点击按钮时再次显示弹出视图。
它会崩溃显示在日志下面。
Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIAlertController () 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.'
*** First throw call stack:
(0x18d9a41c0 0x18c3dc55c 0x19418a8b0 0x193ac60a8 0x193ac3df4 0x193a08d0c 0x1939faac0 0x19376a22c 0x18d9517dc 0x18d94f40c 0x18d94f89c 0x18d87e048 0x18f2ff198 0x1937e2b50 0x1937dd888 0x10011198c 0x18c8605b8)
libc++abi.dylib: terminating with uncaught exception of type NSException
有人知道如何解决这个问题吗?
我的代码如下:
@interface ViewController () <...UITextViewDelegate,UITextFieldDelegate...> {
UIAlertController *alertTypeAlertController;
UIAlertAction *alertType1Action;
UIAlertAction *alertType2Action;
UIPopoverPresentationController *popPresenter;
}
- (void)viewDidLoad {
[super viewDidLoad];
alertTypeAlertController = [UIAlertController
alertControllerWithTitle:@"selecte one:"
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
alertType1Action = [UIAlertAction
actionWithTitle:@"Type1"
style:UIAlertActionStyleDefault
handler:nil];
alertType2Action = [UIAlertAction
actionWithTitle:@"Type2"
style:UIAlertActionStyleDefault
handler:nil];
[alertTypeAlertController addAction: alertType1Action];
[alertTypeAlertController addAction: alertType2Action];
// for ipad
popPresenter = [alertTypeAlertController popoverPresentationController];
popPresenter.permittedArrowDirections = UIPopoverArrowDirectionLeft;
popPresenter.delegate = self;
popPresenter.sourceView = self.theTypeBtn;
popPresenter.sourceRect = CGRectMake(230, 22, 10, 10);
....
}
- (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;
}
-(UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
return UIModalPresentationNone;
}
enter code here
非常感谢。
也许 UIAlertController
和 UIPopoverPresentationController
对象被 ViewController 对象强烈引用,这使得
Popover 关闭后无法释放。
I later found your problem is that you try to create popPresenter
once in the viewDidLoad
method and present it every time you touch
the button,you should create a new one instead,you can move the ViewDidLoad code to a new method,and call it by touch event, fix like this:
- (void)makePopover
{
alertTypeAlertController = [UIAlertController
alertControllerWithTitle:@"selecte one:"
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
alertType1Action = [UIAlertAction
actionWithTitle:@"Type1"
style:UIAlertActionStyleDefault
handler:nil];
alertType2Action = [UIAlertAction
actionWithTitle:@"Type2"
style:UIAlertActionStyleDefault
handler:nil];
[alertTypeAlertController addAction: alertType1Action];
[alertTypeAlertController addAction: alertType2Action];
// for ipad
popPresenter = [alertTypeAlertController popoverPresentationController];
popPresenter.permittedArrowDirections = UIPopoverArrowDirectionLeft;
popPresenter.canOverlapSourceViewRect = YES; // adding this line
popPresenter.delegate = self;
popPresenter.sourceView = self.theTypeBtn;
popPresenter.sourceRect = CGRectMake(230, 22, 10, 10);
}
- (IBAction)touchButton:(id)sender {
[self makePopover];
[self presentViewController:alertTypeAlertController animated:YES completion:nil];
}
我正在修改你的代码,请检查它是否有效。
- (IBAction)actionButton:(UIButton*)sender {
alertTypeAlertController = [UIAlertController
alertControllerWithTitle:@"selecte one:"
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
alertType1Action = [UIAlertAction
actionWithTitle:@"Type1"
style:UIAlertActionStyleDefault
handler:nil];
alertType2Action = [UIAlertAction
actionWithTitle:@"Type2"
style:UIAlertActionStyleDefault
handler:nil];
[alertTypeAlertController addAction: alertType1Action];
[alertTypeAlertController addAction: alertType2Action];
// for ipad
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
popPresenter = [alertTypeAlertController popoverPresentationController];
popPresenter.permittedArrowDirections = UIPopoverArrowDirectionLeft;
popPresenter.delegate = self;
popPresenter.sourceView = self.theTypeBtn;
popPresenter.sourceRect = CGRectMake(230, 22, 10, 10);
}
[self presentViewController:alertTypeAlertController animated:YES completion:nil];
}
我正在使用 objective-c 写关于 UIAlertcontroller
的 UIAlertControllerStyleActionSheet
。
我想在 iPhone 上显示警报 sheet,在 iPad 上显示 popoverPresentationController
。
首先,我设置了 UIPopoverPresentationControllerDelegate
委托。
当我点击我的按钮时,弹出窗口显示正确。
但是我在屏幕上单击关闭了弹出窗口。它会显示下面的警告。
[Warning] <_UIPopoverBackgroundVisualEffectView 0x14be52ef0> is being asked to animate its opacity. This will cause the effect to appear broken until opacity returns to 1.
现在当我点击按钮时再次显示弹出视图。
它会崩溃显示在日志下面。
Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIAlertController () 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.' *** First throw call stack: (0x18d9a41c0 0x18c3dc55c 0x19418a8b0 0x193ac60a8 0x193ac3df4 0x193a08d0c 0x1939faac0 0x19376a22c 0x18d9517dc 0x18d94f40c 0x18d94f89c 0x18d87e048 0x18f2ff198 0x1937e2b50 0x1937dd888 0x10011198c 0x18c8605b8) libc++abi.dylib: terminating with uncaught exception of type NSException
有人知道如何解决这个问题吗?
我的代码如下:
@interface ViewController () <...UITextViewDelegate,UITextFieldDelegate...> {
UIAlertController *alertTypeAlertController;
UIAlertAction *alertType1Action;
UIAlertAction *alertType2Action;
UIPopoverPresentationController *popPresenter;
}
- (void)viewDidLoad {
[super viewDidLoad];
alertTypeAlertController = [UIAlertController
alertControllerWithTitle:@"selecte one:"
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
alertType1Action = [UIAlertAction
actionWithTitle:@"Type1"
style:UIAlertActionStyleDefault
handler:nil];
alertType2Action = [UIAlertAction
actionWithTitle:@"Type2"
style:UIAlertActionStyleDefault
handler:nil];
[alertTypeAlertController addAction: alertType1Action];
[alertTypeAlertController addAction: alertType2Action];
// for ipad
popPresenter = [alertTypeAlertController popoverPresentationController];
popPresenter.permittedArrowDirections = UIPopoverArrowDirectionLeft;
popPresenter.delegate = self;
popPresenter.sourceView = self.theTypeBtn;
popPresenter.sourceRect = CGRectMake(230, 22, 10, 10);
....
}
- (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;
}
-(UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
return UIModalPresentationNone;
}
enter code here
非常感谢。
也许 UIAlertController
和 UIPopoverPresentationController
对象被 ViewController 对象强烈引用,这使得
Popover 关闭后无法释放。
I later found your problem is that you try to create
popPresenter
once in theviewDidLoad
method and present it every time you touch the button,you should create a new one instead,you can move the ViewDidLoad code to a new method,and call it by touch event, fix like this:
- (void)makePopover
{
alertTypeAlertController = [UIAlertController
alertControllerWithTitle:@"selecte one:"
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
alertType1Action = [UIAlertAction
actionWithTitle:@"Type1"
style:UIAlertActionStyleDefault
handler:nil];
alertType2Action = [UIAlertAction
actionWithTitle:@"Type2"
style:UIAlertActionStyleDefault
handler:nil];
[alertTypeAlertController addAction: alertType1Action];
[alertTypeAlertController addAction: alertType2Action];
// for ipad
popPresenter = [alertTypeAlertController popoverPresentationController];
popPresenter.permittedArrowDirections = UIPopoverArrowDirectionLeft;
popPresenter.canOverlapSourceViewRect = YES; // adding this line
popPresenter.delegate = self;
popPresenter.sourceView = self.theTypeBtn;
popPresenter.sourceRect = CGRectMake(230, 22, 10, 10);
}
- (IBAction)touchButton:(id)sender {
[self makePopover];
[self presentViewController:alertTypeAlertController animated:YES completion:nil];
}
我正在修改你的代码,请检查它是否有效。
- (IBAction)actionButton:(UIButton*)sender {
alertTypeAlertController = [UIAlertController
alertControllerWithTitle:@"selecte one:"
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
alertType1Action = [UIAlertAction
actionWithTitle:@"Type1"
style:UIAlertActionStyleDefault
handler:nil];
alertType2Action = [UIAlertAction
actionWithTitle:@"Type2"
style:UIAlertActionStyleDefault
handler:nil];
[alertTypeAlertController addAction: alertType1Action];
[alertTypeAlertController addAction: alertType2Action];
// for ipad
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
popPresenter = [alertTypeAlertController popoverPresentationController];
popPresenter.permittedArrowDirections = UIPopoverArrowDirectionLeft;
popPresenter.delegate = self;
popPresenter.sourceView = self.theTypeBtn;
popPresenter.sourceRect = CGRectMake(230, 22, 10, 10);
}
[self presentViewController:alertTypeAlertController animated:YES completion:nil];
}