Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't preferredContentSize used by iPhone 6 Plus Landscape?

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

like image 784
Kurt Anderson Avatar asked Jul 07 '15 17:07

Kurt Anderson


1 Answers

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

like image 167
matt Avatar answered Sep 20 '22 08:09

matt