11

I've read tons of stuff on this and while most seems to be in regards to the non-storyboard approach, I thought I had pieced bits together and figured it out. However, the following code does not result in my popover being dismissed. The dismissPopoverButtonPressed button in the Popover executes but a breakpoint in the dismissPopover method in the delegate never hits. Would very much appreciate someone casting an eye over the code to spot mistakes.

Thanks

In the following, NewGameViewController contains a UIButton. Pressing this results in the Popover Segue and subsequent display of the popover containing the PopViewController UIView.

NewGameViewController.h

#import "PopViewController.h"
@interface NewGameViewController: UIViewController <DismissPopoverDelegate>
{
    UIPopoverController *popover;
}

NewGameViewController.m

@implementation NewGameViewController
-(void)prepareForSegue:(UIStoryboardPopoverSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"popoverSegue"])
    {
        popover = [(UIStoryboardPopoverSegue *)segue popoverController];
        // getting warning: Assigning to 'id<UIPopoverControllerDelegate>' from incompatible type 'NewGameViewController *const__strong'
        //popover.delegate = self;
    }
}

-(void)dismissPopover
{
    [popover dismissPopoverAnimated:YES];
}

PopViewController.h

@protocol DismissPopoverDelegate <NSObject>
-(void) dismissPopover;
@end

@interface PopViewController: UIViewController
{
    __unsafe_unretained id<DismissPopoverDelegate> delegate;
}

@property (nonatomic, assign) id<DismissPopoverDelegate> delegate;
-(IBAction)dismissPopoverButtonPressed:(id)sender;
@end

PopViewController.m

#import "NewGameViewController.h"
@implementation PopViewController
@synthesize delegate;
-(IBAction)dismissPopoverButtonPressed:(id)sender
{
    [self.delegate dismissPopover];
}
Tony
  • 373
  • 5
  • 18

1 Answers1

13

When linking to a popover controller from a storyboard segue, the popoverController property of the segue refers to a standard UIPopoverController. This controller itself has a property, contentViewController, which will represent the view controller that is actually being presented within the popover, in your case the PopViewController.

So, your current code is setting itself as the delegate of the popover controller, when it really needs to be setting itself as the delegate of the popover's content view controller.

You still need to keep a reference to the popover controller around, to dismiss, so keep your existing code, but make the following change:

-(void)prepareForSegue:(UIStoryboardPopoverSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"popoverSegue"])
    {
        popover = [(UIStoryboardPopoverSegue *)segue popoverController];
        // Get a reference to the content view controller of the popover
        PopViewController *popVC = (PopViewController*)popover.contentViewController;
        // Set ourselves as the content VC's delegate
        popVC.delegate = self;
    }
}
jrturton
  • 118,105
  • 32
  • 252
  • 268
  • Thanks. I must admit, I implemented this code not fully understanding the logic but I recall reading multiple comments about having to explicitly declare a protocol & delegate so that Popover events can be handled in the VC that generates it. Certainly, approaches appear to be different based on whether the Popover is being created explicitly in code vs. through the Storyboard. With that said, I'm still no wiser on the above. – Tony Jun 10 '12 at 17:49
  • I also tried renaming the 'delegate' to prevent clashes as you suggest but it made no difference. When you say that my popover ivar should be more specifically typed - what do you mean exactly? – Tony Jun 10 '12 at 23:06
  • If SHARRP is watching this, would you be so kind as to create an example project (similar to the one you did for http://stackoverflow.com/questions/5922254/how-to-dismiss-uipopover-from-a-button-in-the-popover) that does the same thing but using Storyboard (i.e., control-dragging a segue to the UIViewController whose view will appear inside the Popover). My code above was an attempt to implement your example but something is not right and the use of Storyboard/Segue seems to be the main difference. – Tony Jun 11 '12 at 02:56
  • Sorry, I have looked again at your question and my previous answer was incorrect. Please see my edited one, which hopefully has more explanation and a working solution for you! – jrturton Jun 11 '12 at 06:10
  • jturton - bingo. Thanks very much indeed. Solved my issue. – Tony Jun 12 '12 at 00:25