0
votes

I'm using objective-c write about UIAlertControllerStyleActionSheet of UIAlertcontroller.

I want to show alert sheet on the iPhone, and popoverPresentationController on the iPad.

First, I have set the UIPopoverPresentationControllerDelegate delegate.

When I click my button, the pop over have show is correct.

But I click on the screen dismiss the popover. it will show below warning.

[Warning] <_UIPopoverBackgroundVisualEffectView 0x14be52ef0> is being asked to animate its opacity. This will cause the effect to appear broken until opacity returns to 1.

Now When I click the button show the pop view again.

It will crash show below log.

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

Have anyone know how to resolve the problem?

My code is below:

 @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

Thank you very much.

2

2 Answers

3
votes

Maybe the UIAlertController and UIPopoverPresentationController objects strongly referenced by the ViewController object which makes the Popover can't release after you dismiss it.


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];
}
0
votes

I am just modifying your code, please check if it is working or not.

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