I have a UIPopoverController which is being presented from a UIBarButtonItem. I want touches outside of the popover to dismiss the popover. When presenting a popover from a bar button, the other bar buttons are automatically included in the popovers passthrough views. In order to prevent that I set the passthrough views to nil (or @[ ]) after presenting the popover, like so:
- (IBAction) consoleBarButtonHit:(id)sender {
UIViewController *consoleNavigationController=[self.storyboard instantiateViewControllerWithIdentifier:@"consoleNavigationController"];
_consolePopoverController=[[UIPopoverController alloc] initWithContentViewController:consoleNavigationController];
_consolePopoverController.delegate=self;
[_consolePopoverController presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
// this must be done _after_ presenting the popover in order to work
_consolePopoverController.passthroughViews=nil;
}
That's all fine and good, but the problem that I'm having is that after rotating the device while the popover is visible the bar buttons are being automatically re-added as passthrough views and don't cause the popover to be dismissed.
If I could somehow get the bar buttons view (or rect) then I could present the popover using
-presentPopoverFromRect:inView:permittedArrowDirections:animated:
which would likely fix this problem, but I don't know of any non-hackish way of finding that rect/view from a UIBarButtonItem.
I really don't want the selectors called when the other bar buttons are hit to dismiss the popover programmatically, that's not their responsibility and will likely cause problems for me later.
Any ideas?
So I came up with a solution, that's a little odd, but keeps things modular, works well. I've created a class called PropertyEnforcer which registers itself as a KVO observer of an object's property and re-sets that property any time it changes.
PropertyEnforcer.h:
PropertyEnforcer.m:
Now I can change the change the original code to:
The PropertyEnforcer registers itself as an associated object so we don't ever have to keep track of it. It will automatically unregister itself as a KVO observer and be destroyed whenever the UIPopoverController is destroyed.
This is the best, least hackish, solution that I could come up with.
The solution I went for was to leave
passthroughViews
alone and instead disable/re-enable individual buttons (UIBarButtonItem
instances) in a toolbar or a navigation bar whenUIPopoverPresentationController
is presented and dismissed, based on its transition.(iOS 8:
UIPopoverPresentationController
instead ofUIPopoverController
.)UIPopoverPresentationController+managedBarButtonItems.h
UIPopoverPresentationController+managedBarButtonItems.m
Usage:
Also possible: