3

Possible Duplicate:
How to Dismiss a Storyboard Popover

I have a iPad storyboard. A Bar Button Item in one View is Control-dragged to another view -- and a popover style is chosen. When I press the button the new popover view is shown in a popover, but I have two problems:

  1. When I press the button again, another instance of the popover view is displayed -- I can see, that the black border is getting darker and darker. If the popover view is open and I press the button, the popover view should dismiss. How can I do that?
  2. Currently the new popover view is floating to the button of the screen even if the content in the view is not that heigh. How can I control the dimensions of the popover view?

EDIT1:

I've created a segue by dragging from the yellow controller icon in the bottom of the controller to the other view, which should be inside the popover. The identifier for this popover is settingsPopover.

I then do this inside the IBAction:

- (IBAction)settingsButtonTapped:(id)sender {
        [self performSegueWithIdentifier:@"settingsPopover" sender:self];
}

But this gives me this error:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UIStoryboardPopoverSegue must be presented from a bar button item or a view.'

Have I created the segue in a bad way or in the call to performSegueWithIdentifier wrong?

EDIT2:

I've created this IBAction:

- (IBAction)settingsButtonTapped:(id)sender {
    if (_settingsPopover == nil) {
        SettingsViewController* settingsView = [[SettingsViewController alloc] initWithStyle:UITableViewStylePlain];
        self.settingsPopover = [[UIPopoverController alloc] initWithContentViewController:settingsView];
    }
    [self.settingsPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}

It almost work, but one drawback is that it is not using the UIView designed in my Storyboard. For instance, in my storyboard the view that has the class SettingsViewController in designed as a grouped table view. Is there a way to display the UIView designed in the storyboard inside the popover instead of the raw SettingsViewController instance?

Solution:

I created a global segue in the Storyboard with the identifier "settingsPopover".

- (IBAction)settingsButtonTapped:(id)sender {
    if (self.settingsPopover==nil) {
        [self performSegueWithIdentifier:@"settingsPopover" sender:sender];
    }
}

#pragma mark - UIView
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {    
    if ([segue.identifier isEqualToString:@"settingsPopover"]) {
        self.settingsPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
        self.settingsPopover.delegate = self;
    }
}

#pragma mark - UIPopoverControllerDelegate
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
    self.settingsPopover = nil;
}
Community
  • 1
  • 1
dhrm
  • 14,335
  • 34
  • 117
  • 183

4 Answers4

2

I then do this inside the IBAction:

- (IBAction)settingsButtonTapped:(id)sender {
        [self performSegueWithIdentifier:@"settingsPopover" sender:self];
}

But this gives me this error:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UIStoryboardPopoverSegue must be presented from a bar button item or a view.'

Have I created the segue in a bad way or in the call to performSegueWithIdentifier wrong?

You're passing self instead of sender (the tapped button) when you call -performSegueWithIdentifier:sender: i.e., you're giving the segue a UIViewController where it expects a UIBarButtonItem or UIView.

This should work:

 - (IBAction)settingsButtonTapped:(id)sender {
         [self performSegueWithIdentifier:@"settingsPopover" sender:sender];
 }
Ryder Mackay
  • 2,900
  • 18
  • 29
  • I've changed the sender, but I still gets the same exception. – dhrm Dec 28 '11 at 16:42
  • My mistake. Popover segues also need an anchor point when they're presented this way. Select your segue in interface builder and in the attributes inspector, drag a connection from the anchor field to your bar button item. See this [screenshot](http://cl.ly/Cv2O). – Ryder Mackay Dec 28 '11 at 16:56
1

Storyboards are meant to be a general app flow and interface tool. They abstract a lot of the common boilerplate away from your code so you can easily see what's going on a high-level.

Unfortunately, you aren't going to be able to capture the logic you want purely in Storyboards. Just as Storyboards will gladly present a view controller modally as a segue but has no awareness of dismissing a view controller modally, Storyboards will present popover controllers, but it doesn't offer you the capability to dismiss them.

  1. Instead of using a segue for this, just create a custom IBAction for the bar button. Keep track of whether or not the popover is presented and dismiss it in this method if so.

  2. UIPopoverController has a property called popoverContentSize that lets you control this.

CIFilter
  • 8,647
  • 4
  • 46
  • 66
1

Every time a Segue is performed it creates a new viewController, as you are seeing when you wired your button up to perform the segue. So instead you need to create a "generic" segue for the viewController by dragging from the viewController icon at the bottom to the destination. Then as LucasTizma suggested hook the button up to an IBAction that either calls performSegueWithIdentifier: or dismisses the popover, conditional on whether the popover is on screen or not.

agilityvision
  • 7,901
  • 2
  • 29
  • 28
0

A different solution is here. The segue changes the button action to either display or dismiss the popup.

Community
  • 1
  • 1
Symmetric
  • 4,013
  • 3
  • 27
  • 33