I'm using a UIStoryboardPopoverSegue
to present a popover for an iOS 5 iPad app. The Segue works great, but it seems like the toolbar that contains the button is a passthrough view for the popover controller so if you keep pressing the button, more popovers appear. As I'm not creating and keeping track of the UIPopoverController
myself (as the Storyboard is doing it) I can't dismiss it when the button is touched again. Has anyone else run into this? I have a bug open with Apple but they haven't responded.
EDIT: I've solved this using the answer below. Here is the code I ended up using. currentPopover
is a __weak
ivar in my view controller class, so when the controller is done it will drop to nil automatically.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue isKindOfClass:[UIStoryboardPopoverSegue class]]){
// Dismiss current popover, set new popover
[currentPopover dismissPopoverAnimated:YES];
currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
}
}
There are some visual issues with the your solution Cory.
Two options that can be considered - simply remove or change the action of the button that presents the popover.
Option 1, hold a pointer to the button's action, and after the popover is presented, set the action to nil. Upon dismissal of the popover reset to the original action.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
action = [sender action];
[sender setAction:nil];
self.currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
self.currentPopover.delegate = self;
}
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
[self.navigationItem.rightBarButtonItem setAction:action];
return YES;
}
This way the popover can only appear once, and will be dismissed as expected.
A second option would be to change the function of the button so that when the popover is visible, tapping the button will cause the popover to be dismissed.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
action = [sender action];
target = [sender target];
[sender setTarget:self];
[sender setAction:@selector(dismiss:)];
self.currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
self.currentPopover.delegate = self;
}
-(void)dismiss:(id)sender
{
[self.navigationItem.rightBarButtonItem setAction:action];
[self.navigationItem.rightBarButtonItem setTarget:target];
////or
// [sender setAction:action];
// [sender setTarget:target];
[self.currentPopover dismissPopoverAnimated:YES];
}
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
[self.navigationItem.rightBarButtonItem setAction:action];
[self.navigationItem.rightBarButtonItem setTarget:target];
return YES;
}
Simply connect a UIBarButtonItem
via IBAction
. Use the itendifier set in interface builder:
-(IBAction)barButtonItemPressed:(id)sender {
if (currentPopoverController && currentPopoverController.popoverVisible) {
[currentPopoverController dismissPopoverAnimated:YES];
currentPopoverController = nil;
} else {
[self performSegueWithIdentifier:@"aSegueIdentifier" sender:sender];
}
}
Get a reference of the new UIPopoverCOntroller
from the seque:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"aSegueIdentifier"])
currentPopoverController = [(UIStoryboardPopoverSegue *)segue popoverController];
}
currentPopoverController
is an instance variable, defined in header file:
UIPopoverController *currentPopoverController;
Important: The anchor property of the seque must be set to the corresponding UIBarButtonItem!
You have to store a reference to the popoverController
property passed as part of the UIStoryboardPopoverSegue
class in the prepareForSegue
class method.
To access it, over-ride the method in the calling view controller like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// The Storyboard Segue is named popover in this case:
if ([segue.identifier compare:@"popover"] == NSOrderedSame) {
// segue.popoverController is only present in popover segue's
// self.seguePopoverController is a UIPopoverController * property.
self.seguePopoverController = segue.popoverController;
}
}
Then you can dismiss it in the usual way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With