1

My question is similar to Prevent segue in prepareForSegue method?.

I'm using storyboard where I have two view controllers. In first one I have a button. And in Storyboard I have a seque with popover option from button to second view controller with. If to click on button several times, popover will be opened several times. So that is why I want to check in prepareForSegue method whether popover is already opened. If it is, then do not open it again. So how to prevent seque in prepareForSegue method ?

Community
  • 1
  • 1
Jim
  • 8,874
  • 16
  • 68
  • 125
  • 1
    Wire the button to an IBAction where you can check for the existence of the popover and based on the result do a performSegue command programmatically. – Rog Sep 15 '12 at 13:54
  • It's user sensitive that if i opened popover on button click, than I it should be dismissed on button click to, right ? – Jim Sep 15 '12 at 14:09
  • @Jim Yep, that's very logical, to dismiss the popover if you click the button again. Looks like this is an issue with popovers from navigation bar. Anyway, I've updated my answer with code that does this programmatically. – Rob Sep 15 '12 at 16:19

2 Answers2

2

As the answers to that other question point out, once you hit prepareForSegue, it's too late to cancel it. You need to prevent the segue from being invoked the second time at all, rather than trying to stop it half way through the segue process. You can accomplish this in a variety of ways, depending upon the desired behavior:

First, if you'd like a second click on the button to dismiss the popover, you could (a) remove the segue; and (b) programmatically either present the popover or dismiss it as appropriate:

  1. remove the popover segue from storyboard;
  2. give your popover view a unique identifier so you can instantiate the controller via code;
  3. make sure you have some IBOutlet or other reference to your navigation bar button (in my code sample below, it's myNavBarButton) so that you can tell your popover to be presented from that button;
  4. you might want to also change the simulated metrics for the popover view to be "freeform", because if you leave it to "inferred", Interface Builder will assume you want it to be full screen and will repeatedly resize it for you;
  5. define an ivar for your popover, e.g. UIPopoverController *_popover;;
  6. define and link IBAction for your navigation bar button that does the work of dismissing or presenting of the popover as appropriate; and
  7. make sure to define view controller with the button to be a UIPopoverControllerDelegate so that it can receive and handle the popoverControllerDidDismissPopover event.

Thus, the ARC solution might look like:

@interface MyViewController ()
{
    UIPopoverController *_popover;
}
@end

@implementation MyViewController

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

- (IBAction)navbarButtonClicked:(id)sender
{
    if (_popover)
    {
        // If the popover already is present, dismiss it

        // I'm dismissing the popover here, but if you wanted to do something else,
        // e.g. like do nothing, you could replace these two lines with whatever 
        // behavior you want if the user clicked on the button again.

        [_popover dismissPopoverAnimated:YES];
        _popover = nil;
    }
    else
    {
        // If the popover doesn't exist yet, let's create and present it

        UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"gesturePopover"];
        _popover = [[UIPopoverController alloc] initWithContentViewController:controller];
        [_popover presentPopoverFromBarButtonItem:self.myNavBarButton permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    }
}

// the rest of your main view controller's implementation

@end

Second, you could alternatively just disable the navigation bar button, so you don't get popovers on top of popovers. You'll also have a nice visual indication that it's disabled. So bottom line, you can disable the button in prepareForSegue before you perform the segue and then re-enable it when the popover is dismissed. You will need to define an identifier for your segue in Interface Builder and you'll need an outlet/reference to your navigation bar button so that you can enable and disable it. It would then look like:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"mySegueIdentifier"])
    {
        UIPopoverController *popover = [(UIStoryboardPopoverSegue *)segue popoverController];
        popover.delegate = self;
        self.myNavBarButton.enabled = FALSE;
    }
}

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
    self.myNavBarButton.enabled = TRUE;
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Disable button is not for me, because button is in Navigation Bar. And when user clicked on navigation bar, popover will not be dismissed. ANd also, I cannot remove popover seque from button, did you tried that ? Popover seque should have anchor on view, but not on view controller ) – Jim Sep 15 '12 at 14:05
  • @Jim You can disable buttons in navigation bar if you'd like. But given that you want to dismiss popover when they tap the button again, I've updated my answer with some sample code that does that. And to remove the segue from the button, you click on the icon in the middle of the segue and then hit the `delete` key on your keyboard and it will be removed. But you're quite right that you can't have a popover segue from controller to controller, so you'll see in my code sample that I suggest removing the segue altogether from the storyboard, and do it all via code. – Rob Sep 15 '12 at 15:57
1

I do not understand the question exactly because you will need the segue to make it happen.

Anyway, you can call this function from the UIPopoverControllerDelegate:

  • (void)dismissPopoverAnimated:(BOOL)animated;

maybe this tutorial will help?

http://www.raywenderlich.com/1056/ipad-for-iphone-developers-101-uipopovercontroller-tutorial

YoYoHu
  • 92
  • 1
  • 11