Skip to content

Instantly share code, notes, and snippets.

@jamztang
Created May 16, 2012 10:16
Show Gist options
  • Save jamztang/2709272 to your computer and use it in GitHub Desktop.
Save jamztang/2709272 to your computer and use it in GitHub Desktop.
Handle UIPopoverController for interface orientation changes
//
// The blog post which described this dedicated problem
// http://mystcolor.me/post/23158981244/uipopovercontroller-and-orientation-positioning-problem
//
typedef void (^PopoverControllerPresentationBlock)(void);
@interface ViewController () <UIPopoverControllerDelegate>
@property (nonatomic, strong) UIPopoverController *popoverController;
@property (nonatomic, copy) PopoverControllerPresentationBlock popoverControllerPresentationBlock;
@end
@implementation ViewController
- (IBAction)showButtonPressed:(id)sender {
__block __weak UIButton *button = sender;
__block __weak ViewController *weakSelf = self;
// Save the presentation action in a block
self.popoverControllerPresentationBlock = ^(void){
[self.popoverController presentPopoverFromRect:[button convertRect:button.bounds toView:weakSelf.view]
inView:weakSelf.view
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
};
// invoke the presentation block to show the popover now
self.popoverControllerPresentationBlock();
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
if (self.popoverControllerPresentationBlock) {
// While orientation changed, re-invoke the presentation block
self.popoverControllerPresentationBlock();
}
}
#pragma mark UIPopoverViewControllerDelegate
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
// Clear the presentation block so the popover won't be re-presented after user really dismiss it
self.popoverControllerPresentationBlock = nil;
self.popoverController = nil;
}
@end
@eyeplum
Copy link

eyeplum commented Mar 20, 2013

If I have set the self.popoverController.popoverLayoutMargins property, I have to set both self.popoverController and self. popoverControllerPresentationBlock to nil in the didRotateFromInterfaceOrientation: callback. Or the popover will display incorrectly.

My code here:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    if (self.popoverPresentationBlock) {
        [self.popoverController dismissPopoverAnimated:NO];
        self.popoverController = nil;

        self.popoverPresentationBlock = nil;

        // recreate self.popoverController
        // reset self.popoverController.popoverLayoutMargins
        // recreate self.popoverPresentationBlock

        self.popoverControllerPresentationBlock();
    }
}

This hack will work fine unless the popoverController has a UINavigationController in it and the user has gone deep into the navigation stack when the device orientation change happens (in this condition the popover will be recreated so does the UINavigationController, and the user will have to redo the navigate operations).

I'm wondering if there is a better solution...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment