applejuiceteaching
applejuiceteaching

Reputation: 1493

ios 9 UIPopoverPresentationController constant placement on rotation

in iOS9 when I rotate my screen with a UIPopoverPresentationController the coordinates are reset to 0 and not attached to my sourceView which is a button.

I have tried:

func popoverPresentationController(popoverPresentationController: UIPopoverPresentationController, willRepositionPopoverToRect rect: UnsafeMutablePointer, inView view: AutoreleasingUnsafeMutablePointer) { rect.initialize(CGRectMake(200, 200, 400, 400)) }

but no avail. Any help ?

Upvotes: 0

Views: 1365

Answers (1)

Dmitry
Dmitry

Reputation: 386

You could apply constraints to you sourceView button, then just use it as the popover source:

myPopoverViewController.popoverPresentationController?.sourceView = button

You also can set sourceView in the storyboard, but sourceRect needs to be set in code:

myPopoverViewController.popoverPresentationController?.sourceRect = button.bounds

You need the correct source rect for the popover arrow to align properly. Now you don't need to dismiss and present the popover on rotation. UIPopoverPresentationController does that for you. You don't even need to update sourceView/sourceRect once they are set on creating the popover.

Use viewWillTransition to catch size and orientation changes:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    coordinator.animate(alongsideTransition: { _ in
        if self.popover != nil {
            // optionally scroll to popover source rect, if inside scroll view
            let rect = ...
            self.scrollView.scrollRectToVisible(rect, animated: false)

            // update source rect constraints
            buttonConstraint.constant = ...
            button.setNeedsLayout()
            button.layoutIfNeeded()
        }
    }, completion: nil)
}

Explanation: The trick with animate(alongsideTransition: ((UIViewControllerTransitionCoordinatorContext) -> Void)?, completion: ((UIViewControllerTransitionCoordinatorContext) -> Void)? = nil) is that you should update your constraints in alongsideTransition closure, not in completion. This way you ensure that UIPopoverPresentationController has the updated sourceRect when restoring the popover at the end of rotation.

What might seem counter-intuitive is that inside alongsideTransition closure you already have your new layout that you derive your constraints calculation from.

Upvotes: 2

Related Questions