Problem with UIModalPresentationPopover on both iPhone and iPad with iOS 13

Starting with iOS 13 I'm having issue with popover used as main menu.


    MainMenuViewController *vc = [[MainMenuViewController alloc] initWithNibName:@"MainMenuViewController" bundle:nil];
    vc.recentConnections = _recentConnections;
    vc.preferredContentSize = CGSizeMake(300, 372);
    vc.modalPresentationStyle = UIModalPresentationPopover;
    
    vc.popoverPresentationController.barButtonItem = self.navigationItem.leftBarButtonItem;
    vc.popoverPresentationController.delegate = self;
    
    [self presentViewController:vc animated:YES completion:nil];
   

Before iOS13

http://www.realadsb.com/img/before13.png


iOS13

http://www.realadsb.com/img/starting13.png


As you can see window inside popover goes underneath arrow and that was not the case before

Replies

This is a change in iOS 13 that seems wrong, but is deliberate according to Tyler Fox (Apple employee): https://twitter.com/smileyborg/status/1157707042955513856


"It’s a feature. Popovers in iOS 13 use safe area to do this. You’re free to do things like add a visual effect view outside the safe area, much like what many apps do at the top of the screen in the status bar region on iPhone X."


The popover view's frame now includes the arrow. If you use autolayout and constrain to the Safe Area at the top it should work (on iOS 13 and earlier).

Thank you for pointing me to right direction!


I was able to sort of fix it in view controller using

- (void)viewDidAppear:(BOOL)animated
{
    self.view.frame = CGRectMake(0, 15, 300, 370);
}


But it creates noticable visual jump of the window from incorrect to correct location.


I still consider such behavior a bug since it's not backward compatible and not buying anything from functional point of view.

If you're setting frames manually rather than using autolayout, making the change in viewWillLayoutSubviews in the view controller might ensure the position is updated before you can see it on screen.


If you still need to support older versions of iOS, you presumably don't want to change the frame. Use an @available check to conditionally only run your fix on iOS 13 and later.


Also, remember to call super when you override the viewWill/DidXXX methods!

Definitely a bug. When you have a situation where you use UIPopoverArrowDirectionAny you will see that the problem only exists when the arrow is at the top or left of the popover and not when the arrow appears at the right or the bottom of the popover. If you make adjustments in your code to compensate it will work if you use UIPopoverArrowDirectionUp or UIPopoverArrowDirectionLeft but will not display correctly using that adjustment when using UIPopoverArrowDirectionAny and the popup appears above or to the right of the target rectangle.

Hard for me to understand why anyone would think that this change would be useful to any developer.