11

In my iOS 8 app, this popover segue appears correctly on all devices in all orientations except for iPhone 6 Plus landscape:

Good popover

This is how it looks on iPhone 6 Plus landscape (it is stretching almost from top to bottom): Bad popover

And when it displays like this, clicking outside of the view doesn't dismiss it (although Cancel does work). Rotating back to portrait gets it back to normal.

All of the constraints in this UIViewController are installed on all size classes.

When debugging values in viewDidAppear: I see the following:

  • po self.view: frame = (0 0; 250 394)
  • po self.preferredContentSize (width = 250, height = 160)

What is causing the view's height to jump to 394?

I'm actually having the same issue with another popover segue in iPhone 6 Plus landscape as well. (And in case there was curiosity, I'm using a VC instead of 'UIAlertController' here because of the validation requirements of the UITextField displayed don't work well with UIAlertController.)

Edit to include my popover code:

This code is found in prepareForSegue:

    FavoriteNameViewController *nameVC = segue.destinationViewController;
    UIPopoverPresentationController *popPC = nameVC.popoverPresentationController;
    popPC.delegate = self;
    nameVC.delegate = self;
    nameVC.view.center = self.originalContentView.center;

And then the delegate method:

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
    return UIModalPresentationNone;
}

And here is the segue definition in Xcode: enter image description here

Kurt Anderson
  • 932
  • 1
  • 10
  • 26

1 Answers1

20

What you're seeing is not a popover. It's a normal presented view. By default, a popover appears as a popover on iPad, but as a presented view on iPhone — including the iPhone 6 plus. On other iPhones, this presented view is fullscreen - it covers everything. But the iPhone 6 is so wide that they don't do that, so it appears in the middle of the screen at a standard width (the width of a smaller iPhone).

Thus, the preferred content size has no effect. This isn't a popover. Presented view controller views are given a standard size, and this one is no exception.

However, you can have the popover appear as a popover on iPhone. To do so:

  • Set a delegate for the popover view controller's popoverPresentationController before presenting it.

  • In the delegate, implement adaptivePresentationStyleForPresentationController: and return .None.

However, this is apparently not working on iPhone 6 Plus in landscape mode; the popover is not "adapting". I would describe this as a bug!

EDIT In iOS 9, the problem is solved! Implement the new delegate method adaptivePresentationStyleForPresentationController:traitCollection: to return .None and you'll get a popover under all circumstances, including the iPhone 6 Plus in landscape. Here's a complete working example where the popover is created and summoned in code in response to a button tap:

@IBAction func doButton(sender: AnyObject) {
    let vc = MyViewController()
    vc.preferredContentSize = CGSizeMake(400,500)
    vc.modalPresentationStyle = .Popover
    if let pres = vc.presentationController {
        pres.delegate = self
    }
    self.presentViewController(vc, animated: true, completion: nil)
    if let pop = vc.popoverPresentationController {
        pop.sourceView = (sender as! UIView)
        pop.sourceRect = (sender as! UIView).bounds
    }
}
func adaptivePresentationStyleForPresentationController(
    controller: UIPresentationController, 
    traitCollection: UITraitCollection) 
    -> UIModalPresentationStyle {
        return .None
}

enter image description here

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • given the edits I added, it sounds like I'm already doing what you're suggesting. – Kurt Anderson Jul 07 '15 at 17:28
  • And is that delegate method being called? – matt Jul 07 '15 at 18:13
  • It is. I just confirmed it in debug. – Kurt Anderson Jul 07 '15 at 18:18
  • I see the problem, I think. Check one of the arrow Directions checkboxes? (Just try it and see if it helps...) – matt Jul 07 '15 at 18:37
  • Nope, that isn't going to fix it. – matt Jul 07 '15 at 18:42
  • 1
    I did a lot of testing and I think you've found a bug. Let me know if you're too busy to report it to Apple; I'll do it if you like. – matt Jul 07 '15 at 18:50
  • I appreciate you looking into this. If you don't mind, please report the bug. Is there a link you can provide of the bug report (if it's public)? I'm not familiar with the bug reporting process. – Kurt Anderson Jul 07 '15 at 18:54
  • This bug is now fixed in iOS 9. I can't tell whether the fix is iOS 9 only or whether it works backwards all the way to iOS 8.3. – matt Aug 31 '15 at 00:31
  • Hi Matt. Thanks for the response, and sorry for my delay responding. I'm a bit confused b/c your answer seems to indicate to implement a method that I already have implemented. Maybe I'm not following what you're saying. I'm still getting the odd appearance in landscape at iOS 9. Sidenote: this isn't an issue on iPad. – Kurt Anderson Dec 07 '15 at 01:57
  • 7
    Please read _carefully_ what I said. Look _carefully_ at my code. Note please that the method I'm talking about which fixes the problem, `adaptivePresentationStyleForPresentationController:traitCollection:`, is _not the same_ as the old `adaptivePresentationStyleForPresentationController:` that your code shows you were implementing before. It behaves completely differently. It solves the problem, and my screen shot proves it. – matt Dec 07 '15 at 03:11
  • Thanks, Matt. TBH I thought I was looking at it closely, but clearly I missed it. That method did work. Many thanks! – Kurt Anderson Dec 07 '15 at 03:18
  • Cool! Glad that took care of it. I was very pleased to see this change and that's why I reported back. – matt Dec 07 '15 at 03:29
  • I installed the 8.1 simulator. Looks like the old adaptive method is needed for iOS 8.0-8.2. The 8.1 6Plus landscape simulator is working... but as an fyi - it doesn't break on either `adaptive...` method. – Kurt Anderson Dec 07 '15 at 04:03
  • I don't get what you mean. I already said this fix applies only to iOS 9 and possibly 8.3. Obviously we can't change the past: the bug in 8.0, 8.1, 8.2 does not magically vanish. – matt Dec 07 '15 at 12:52