Uipopovercontroller Dealloc Reached While Popover Is Still Visible

UIPopovercontroller dealloc reached while popover is still visible

UIPopoverControllers should always be held in an instance variable. It is a good practice to create a strong property for it.

UPDATE:

As of iOS 8 you should be using UIPopoverPresentationController. Then you don't need to keep a reference to the popover because it is managed by the presentation controller.

Code example (works both on iPhone and iPad):

UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.allowsEditing = YES;
picker.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController* popoverPC = picker.popoverPresentationController;
popoverPC.barButtonItem = bbItem;
popoverPC.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:picker animated:YES completion:nil];

Why am I still getting -[UIPopoverController dealloc] reached while popover is still visible

check popoverController is visible or not in showModalTime method because popoverController overwrite

  if ([popoverController isPopoverVisible]) {
[popoverController dismissPopoverAnimated:YES];
}

Dismissing Popover, [UIPopoverController dealloc] reached while popover is still visible

First off, it would be advisable to check if the popover is being presented, this will conveniently also check if it is allocated:

if ([self.popover isPopoverVisible]) {
[self.popover dismissPopoverAnimated:NO];
}

Now, the issue is, you don't get the delegate callback - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController if you dismiss the popover programmatically like this, but you need a strong reference to the popover until it is no longer visible.

The way to do this is delay setting the property to nil until you return to the main run loop, as when you get back to the main run loop, all animations will have finished and thus the popover will no longer be visible.

You will want to move the code setting the popover to nil into another method:

- (void)releasePopover {
self.popover.delegate = nil;
self.popover = nil;
}

Then, in your rotation callback, add this method to fire on the main run loop, I like to do this by adding an invocation operation to the main run loop:

if ([self.popover isPopoverVisible]){
[self.popover dismissPopoverAnimated:NO];
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(releasePopover) object:nil];
[[NSOperationQueue mainQueue] addOperation:invocationOperation];
}

Finally, for the sake of cleanliness, you will probably want to call -releasePopover from inside your - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController callback.

So, putting it all together:

- (void)releasePopover
{
self.popover.delegate = nil;
self.popover = nil;
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if ([self.popover isPopoverVisible]){
[self.popover dismissPopoverAnimated:NO];
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(releasePopover) object:nil];
[[NSOperationQueue mainQueue] addOperation:invocationOperation];
}
}

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
[self releasePopover];
}

Having said all that, unless there is a good reason, you may just want to keep the popover around to reuse and only set it to nil when you get low-memory warnings and/or if your view is unloaded, as Chris Loonam's answer mentioned

UIpopoverController dealloc reached while popover is still visible in Ipad

Your problem is that you are dismissing the view without dismissing the popover first.

You can make sure it is dismissed overriding viewWillDisappear

-(void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if (self.popoverController != nil) {
[self.popoverController dismissPopoverAnimated:animated];
self.popoverController=nil;
}
}

You should also add the UIPopoverControllerDelegate method popoverControllerDidDismissPopover: -

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
self.popoverController=nil;
}

UPDATE

Your if statement in the didFinishPickingMediaWithInfo should be either

if ([picker sourceType] == UIImagePickerControllerSourceTypeCamera){

or

if (picker.sourceType == UIImagePickerControllerSourceTypeCamera){

You had the ] in the wrong place.

-[UIPopoverController dealloc] reached while popover is still visible

Here is a complete popover management example:

@interface ViewController () <UIPopoverControllerDelegate>
@property (nonatomic, strong) UIPopoverController* currentPop;
@end

@implementation ViewController

-(IBAction)doPopover1:(id)sender {
Popover1View1* vc = [[Popover1View1 alloc] initWithNibName:@"Popover1View1" bundle:nil];

UIPopoverController* pop = [[UIPopoverController alloc] initWithContentViewController:vc];
self.currentPop = pop;
[pop presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
pop.passthroughViews = nil;
// make ourselves delegate so we learn when popover is dismissed
pop.delegate = self;
}

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)pc {
self.currentPop = nil;
}

By checking self.currentPop you can make sure you don't present two popovers at once (illegal anyway).

Pop Over Error -[UIPopoverController dealloc] reached while popover is still visible

You instantiate the popover and assign it to a local variable here:

UIPopoverController *popoverController=[[UIPopoverController alloc] initWithContentViewController:imagePickerController];

As soon as the method returns, the variable goes out of scope and the object is deallocated since it has no owner anymore.

What you should do is declare a strong property to assign the popover to. You have already done so with your pop property. So now all you need to do is at the time you allocate the popover, assign it to your property. This makes you the owner of the object so it won't get deallocated.

self.pop = [[UIPopoverController alloc] initWithContentViewController:imagePickerController];
[self.pop presentPopoverFromRect:((UIButton *)sender).bounds inView:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

Hope this helps!

reached while popover is still visible

think autorelease is incorrect, here is a tutorial

http://www.jannisnikoy.nl/index.php/2010/04/ipad-tutorial-creating-a-popoverviewcontroller



Related Topics



Leave a reply



Submit