iOS弹出窗口显示两次会崩溃

iOS popover show twice will crash

我正在使用 objective-c 写关于 UIAlertcontrollerUIAlertControllerStyleActionSheet

我想在 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

非常感谢。

也许 UIAlertControllerUIPopoverPresentationController 对象被 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];
  }