How to restore UIPopoverController with iOS State Restoration?

285 views Asked by At

In one of my apps I've implemented state restoration and am currently working on an iPad version. In the iPad version I'm using UIPopoverController for displaying view controllers, but I'm unable to find out how those popover controllers should be saved and restored.

UIPopoverController doesn't inherit from UIViewController and hence doesn't have restorationIdentifier and restorationClass properties I could make use of.

Am I responsible for saving the popover controller's targetRect and encoding it's contentViewController manually in my main view controller so I can restore it during its -decodeRestorableStateWithCoder: method or is there an easier way I just couldn't find in the documentation?

Fabain

1

There are 1 answers

0
Fabian Kreiser On

Given that you have a property popoverControllerRestorationDictionary for storing additional information about the popover controller currently being presented, here is an idea of how you could restore popover controllers:

- (void)presentPopoverController:(UIPopoverController *)popoverController fromRect:(CGRect)rect animated:(BOOL)animated
{
    [popoverController presentPopoverFromRect:rect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:animated];

    self.popoverControllerRestorationDictionary = @{ @"popoverController" : popoverController, @"rect" : [NSValue valueWithCGRect:rect] };
}

- (void)dismissedPresentedPopoverController
{
    self.popoverControllerRestorationDictionary = nil;
}

- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
    ...

    if (self.popoverControllerRestorationDictionary != nil) {
        [coder encodeBool:YES forKey:@"restorePopoverController"];

        UIPopoverController *popoverController = [self.popoverControllerRestorationDictionary objectForKey:@"popoverController"];
        [coder encodeObject:popoverController.childViewController forKey:@"popoverController.childViewController"];

        NSValue *rectValue = [self.popoverControllerRestorationDictionary objectForKey:@"rect"];
        [coder encodeObject:rectValue forKey:@"popoverController.targetRect"];
    }
}

- (void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
    ...

    if ([coder decodeObjectForKey:@"restorePopoverController"]) {
        UIViewController *childViewController = [coder decodeObjectForKey:@"popoverController.childViewController"];
        CGRect targetRect = [[coder decodeObjectForKey:@"popoverController.targetRect"] CGRectValue];

        UIPopoverController *popoverController = [[UIPopoverController alloc] initWithChildViewController:childViewController];

        [self presentPopoverController:popoverController fromRect:targetRect animated:NO];
    }
}

This solution is suboptimal at best, so if anyone comes up with something better, please let me know!