Question

I have a UIPopoverController that contains a UITableViewController within a UINavigationController. Whenever a cell in this table view is pressed, I push yet another UITableViewController to my navigation Controller.

I want to set the height of my second table view (let's say to 200) and adjust the size of the popover accordingly.

I therefore first set the table view frame in viewDidAppear:(BOOL)animated and then call setPopoverContentSize:(CGSize)size animated:(BOOL)animated. Both heights are set to 200.

The resizing works, but there are the following differences on the different iOS versions:

iOS 6.1

  • As intended: The resized popover has the height 200 + the height of the navigation bar.

iOS 7.0

  • Not as intended: The resized popover has the height 200, including the height of the navigation bar.

iOS 7.1

  • As intended: The resized popover has the height 200 + the height of the navigation bar.
  • The resizing is for some reason animated, the table view is shortly displayed behind the navigation bar.

I can live with the different heights as those can be adjusted depending on the iOS version. I don't like the ugly animation, though. Do you have any idea how I can achieve my goal without this glitch?

Here comes a screenshot of the effect I want to avoid:

enter image description here

Here's, how I create the UIPopoverController:

- (IBAction)showPopup:(id)sender
{
    MyTableViewController *table = [[MyTableViewController alloc] initWithStyle:UITableViewStylePlain];

    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:table];
    nav.navigationBar.tintColor = [UIColor orangeColor];

    UIPopoverController *pop = [[UIPopoverController alloc] initWithContentViewController:nav];

    table.parentPopover = pop;

    UIView *origin = (UIView *)sender;
    CGRect buttonRect = CGRectMake(origin.frame.origin.x, origin.frame.origin.y, origin.frame.size.width, origin.frame.size.height);
    [pop presentPopoverFromRect:buttonRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}

When a table cell is pressed, I push another table view controller:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [self.tableView deselectRowAtIndexPath:indexPath animated:YES];

    MyNextTableViewController *next = [[MyNextTableViewController alloc] initWithStyle:UITableViewStylePlain];
    next.parentPopover = self.parentPopover;
    [self.navigationController pushViewController:next animated:YES];
}

And here's what I do to resize the 'final' table view and the popover:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    self.tableView.frame = CGRectMake(0, 0, self.tableView.frame.size.width, 200);
    [self.parentPopover setPopoverContentSize:[self contentSizeForViewInPopover] animated:NO];
}

- (CGSize)contentSizeForViewInPopover
{
    return CGSizeMake(320, self.tableView.frame.size.height);
}

Btw, I know that - (CGSize)contentSizeForViewInPopover is deprecated from iOS 7.0 on, but I want to support iOS 6 and the problem described above also occurs when using - (CGSize)preferredContentSize. Same problem with UIScrollView, not only UITableView.

EDIT: I filed a bug report with Apple with bug number 16865330.

Was it helpful?

Solution

This is a bug in popover controller in iOS7 and above. Please open a bug report with Apple in https://bugreport.apple.com and post the bug number in your question.

This happens due to resizing the popover controller in viewDidAppear. The key is to delay the resizing just a little bit, so that the popover controller can finish its layout. Using dispatch_async on the main queue, you register your block to run on a followup pass of the main runloop, which gives the popover controller enough time to "breed" and the bug is not reproduced.

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    self.tableView.frame = CGRectMake(0, 0, self.tableView.frame.size.width, 200);

    dispatch_async(dispatch_get_main_queue(), ^{
        [self.parentPopover setPopoverContentSize:[self contentSizeForViewInPopover] animated:NO];
    });
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top