3
votes

I have a button which leads to a popOver, all created in Interface Builder. The popOver is closed when I press somewhere outside of it, but I would also like to implement a button within the popOver which does that.

I found a solution by Giorgio Barchiesi dating back to 2011, however I fail to implement it. Here's his solution:

In the implementation file of the source view controller:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue destinationViewController] isKindOfClass:[MyDestViewController class]]) {
        MyDestViewController* viewController = (MyDestViewController*)[segue destinationViewController];
        UIStoryboardPopoverSegue* popoverSegue = (UIStoryboardPopoverSegue*)segue;
        [viewController setPopoverController:[popoverSegue popoverController]];
    }
}

In the header file of the destination view controller:

@property (weak, nonatomic) UIPopoverController* popoverController;

In the implementation file of the destination view controller:

@synthesize popoverController;

Same file, whenever you want to dismiss the popover:

[popoverController dismissPopoverAnimated:YES];

i could call the last function when the button is pressed. My problem is that XCode gives me an error on the [viewController setPopoverController:[popoverSegue popoverController]] line: ARC Semantic Issue: No known class method for selector 'setPopOverController'

What did I miss to implement?

4

4 Answers

2
votes

Here is the method I use:

Open your storyboard file, select the segue arrow and open the Attributes Inspector (Option - Command - 4) and identifier fill in a sensible name, like "myPopoverSegue".

In your Source View Controller define a variable right after @implementation :

@implementation ViewController
{
    __weak UIPopoverController *myPopover;
}

Then, again in the Source VC:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if ([segue.identifier isEqualToString:[dict objectForKey:@"myPopoverSegue"]]) {//@"segue" is your segue name. You can use isKindOfClass as you do currently, I prefer this method.
        myPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
    }
}

-(void)closePopover{
    [myPopover dismissPopoverAnimated:YES];
}

In the end of your Source VC's viewDidLoad method write:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closePopover) name:@"popoverShouldDismiss" object:nil];

Finally, whenever you want to dismiss the popover:

 [[NSNotificationCenter defaultCenter] postNotificationName:@"popoverShouldDismiss" object:nil];

Hope this helps! This way you will also be able to change the segue to a different controller without changing your code.

1
votes

You can add the delegate < UIPopoverControllerDelegate > to your class and override the delegate method:

 - (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
 {
     return NO;
 }

This will prevent the popover to be dismissed when user presses anywhere on screen. Now you can dismiss your popover inside the button's selector method by using:

  [popoverController dismissPopoverAnimated:YES];
1
votes

In iOS 8 it's really easy. Just call

[self dismissViewControllerAnimated:YES completion:^{}];

Pop overs are regular presentation controllers, so it's more or less the exact same thing as a modal view controller.

0
votes

Try this code

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue destinationViewController] isKindOfClass:[MyDestViewController class]]) 
    {
        MyDestViewController* viewController = (MyDestViewController*)[segue destinationViewController];

        UIStoryboardPopoverSegue* popoverSegue = (UIStoryboardPopoverSegue*)segue;

        popoverSegue.popoverController=[[UIPopoverController alloc] initWithContentViewController:viewController];

        [popoverSegue.popoverController setPopoverContentSize:CGSizeMake(viewController.view.frame.size.width, viewController.view.frame.size.height)];

        popoverSegue.popoverController.delegate=self;

        [viewController setPopoverController:popoverSegue.popoverController];
    }
}

I hope it helps you.