I have a UIPopoverController stored in a strong property in my View Controller. When the user rotates the iPad while the popover is visible, I dismiss the popover and set my property to nil.
if (self.popover != nil) {
[self.popover dismissPopoverAnimated:NO];
self.popover.delegate = nil;
self.popover = nil;
}
When the code gets to self.popover = nil, ARC attempts to dealloc the UIPopoverController, but it crashes because it is supposedly still visible.
How am I supposed to dismiss and nil out the popover without it crashing?
First off, it would be advisable to check if the popover is being presented, this will conveniently also check if it is allocated:
Now, the issue is, you don’t get the delegate callback
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverControllerif 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:
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:
Finally, for the sake of cleanliness, you will probably want to call
-releasePopoverfrom inside your- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverControllercallback.So, putting it all together:
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