Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

popoverPresentationController displaying modally from UITableViewController on iPhone

I'm having an issue displaying a UIViewController with a popover presentation from iPhone within a UITableViewController. The code I have been using works to display a popover from any other UIViewController, just not a UITableViewController on iPhone. It does work from a UITableViewController on iPad.

When the code is executed, the view is presented modally temporarily (as you might expect if I did not implement adaptivePresentationStyleForPresentationController) and then covered by black, as if some sort of Auto Layout error occurred (though there's nothing in the console to indicate otherwise).

As I mentioned, the following works outside of a UITableViewController on iPhone, and works all the time on iPad. I'm sure I'm missing something fairly simple. Any ideas?

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    /* Create label */
    UILabel *label = [UILabel new];
    label.text = @"This should be in a popover.";
    label.numberOfLines = 0;
    label.lineBreakMode = NSLineBreakByWordWrapping;

    /* Add label to new ViewController */
    UIViewController *popoverVC = [UIViewController new];
    [popoverVC.view addSubview:label];
    label.translatesAutoresizingMaskIntoConstraints = NO;
    [popoverVC.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[label]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(label)]];
    [popoverVC.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[label]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(label)]];

    /* Define ViewController to present as a popover and display */
    popoverVC.modalPresentationStyle = UIModalPresentationPopover;
    popoverVC.preferredContentSize = CGSizeMake(320, 50);
    [self presentViewController:popoverVC animated:YES completion:nil];

    /* Grab handle to ViewController's popoverPresentationController after displaying */
    UIPopoverPresentationController *popoverController = [popoverVC popoverPresentationController];
    if (popoverController == nil)
        NSLog(@"popoverController is nil");
    else {
        popoverController.delegate = self;
        popoverController.popoverLayoutMargins = UIEdgeInsetsMake(15, 15, 15, 15);
        popoverController.sourceView = tableView;
        popoverController.sourceRect = [tableView rectForRowAtIndexPath:indexPath];

        self.definesPresentationContext = YES;
    }
}

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection
{
    NSLog(@"%s", __PRETTY_FUNCTION__);
    return (UIModalPresentationNone);
}

FWIW: One way to quickly prototype this code is to add the above to MasterViewController.m from a new "Master-Detail Application" template in Xcode, and define this message to avoid pushing the DetailViewController:

- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
    return (NO);
}

You'll also need to set MasterViewController.h to adopt the UIPopoverPresentationControllerDelegate protocol.

like image 307
greg Avatar asked Nov 08 '22 18:11

greg


1 Answers

The reason for the black color is simple.

Your controller is transparent (you have not set any background color to its view). The presentation animation makes it appear over the table view but once the animation ends, the views under are removed from the hierarchy and you end up with window background color (black by default) and your transparent controller with a black label.

Set

popoverVC.view.backgroundColor = [UIColor yellowColor];

and you will see the controller behave correctly.

I am not sure why your controller is not shown as a popover because you are doing everything correctly according to the documentation. However, moving

[self presentViewController:popoverVC animated:YES completion:nil];

to be the last line of the method fixes the problem. Note: according to the documentation this shouldn't even work.

like image 199
Sulthan Avatar answered Nov 15 '22 06:11

Sulthan