Jim
Jim

Reputation: 9234

IPhone: Prevent popover segue in prepareForSegue method?

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 ?

Upvotes: 1

Views: 2421

Answers (2)

Rob
Rob

Reputation: 437532

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;
}

Upvotes: 2

YoYoHu
YoYoHu

Reputation: 92

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

Upvotes: 1

Related Questions