7
votes

I wanted to play with UIPopupController, and I understood that I can't detect when my popover dismiss. My steps:
1. Create example from XCode (File -> New Project - > Utilitiy Application)
2. Add to MainViewController.h UIPopoverControllerDelegate

#import "FlipsideViewController.h"

@interface MainViewController : UIViewController <FlipsideViewControllerDelegate,UIPopoverControllerDelegate>

@property (strong, nonatomic) UIPopoverController *flipsidePopoverController;

- (IBAction)showInfo:(id)sender;

@end
  1. In MainViewController:

    - (IBAction)showInfo:(id)sender
    {
        if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
            FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:@"FlipsideViewController" bundle:nil];
            controller.delegate = self;
            controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
            [self presentModalViewController:controller animated:YES];
        } else {
            if (!self.flipsidePopoverController) {
                FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:@"FlipsideViewController" bundle:nil];
                controller.delegate = self;

                self.flipsidePopoverController.delegate = self

                self.flipsidePopoverController = [[UIPopoverController alloc] initWithContentViewController:controller];
            }
            if ([self.flipsidePopoverController isPopoverVisible]) {
                [self.flipsidePopoverController dismissPopoverAnimated:YES];
            } else {
                [self.flipsidePopoverController presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
            }
        }
    }

    -(void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
    {
        NSLog(@"OLOLO");
    }

But when I tap somewhere, and popover disappears, there is no NSLog message in Console. What am I doing wrong?

4
You are setting the delegate BEFORE you instantiate the popover controller. In other words, it doesn't exist when you set the delegatespring

4 Answers

15
votes

set the delegates of the popover to self and also you can use two popover delegates i.e :-

 /* Called on the delegate when the popover controller will dismiss the popover. Return NO to prevent the dismissal of the view.
 */
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController;

/* Called on the delegate when the user has taken action to dismiss the popover. This is not called when -dismissPopoverAnimated: is called directly.
 */
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController;
5
votes

Earlier answers have suggested using the UIPopoverControllerDelegate which appears to be the only sensible way to achieve the objective. I thought it would be good to add a practical example as it's not the simplest thing to get your head round. My requirement was simple - I wanted the background view to be blurred whilst the popover is visible, so here are the steps:

  1. Wire up your popover in a storyboard, configure it's popover content size in the destination view controller attributes.

  2. Make your source view controller a UIPopoverControllerDelegate by opening the .h file and doing something like this:

    @interface MyController : UIViewController <UIPopoverControllerDelegate>
    
  3. Override prepareForSegue, assign your source view controller as the delegate for the popover and then set alpha to 0.5 just before the segue presents the destination:

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
        UIStoryboardPopoverSegue* popover = (UIStoryboardPopoverSegue*)segue;
        popover.popoverController.delegate = self;
        self.view.alpha = 0.5;
    }
    
  4. Implement the popover delegate method popoverControllerDidDismissPopover. Set alpha back to 1.0 and unassign ourselves as the delegate to make sure we don't stop ARC doing it's job:

    -(void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
        self.view.alpha = 1.0;
        popoverController.delegate = nil;
    }
    
2
votes

Did you set your MainViewController instance as the delegate of the popover?

(if you create the popover through code) popover.delegate = self;

0
votes
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
UIStoryboardPopoverSegue *popoverSegue;
popoverSegue = (UIStoryboardPopoverSegue *)segue;
popoverController = popoverSegue.popoverController;
pCVisible = YES;
[[segue destinationViewController] setDelegate:self];
}

- (void) setDataFromPopover {
  if (pCVisible) {
     [popoverController dismissPopoverAnimated:YES]; // THIS IS KEY!   this is where the popover is dismissed, not in the popover itself
  }
}

And

//TableViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:       (NSIndexPath *)indexPath
{
   //variable = whatever

OtherViewController *initialView;
initialView=(OtherViewController *)self.delegate;
initialView.theLabel.text = variable;
[initialView setDataFromPopover];
}