iospopoverswift5uipopoverpresentationcontroller

popover permittedArrowDirections = .left/.right messes with popover framing


Since migration to Swift 5, popovers that have permittedArrowDirections set to .left/.right render slightly off-center from where they're supposed to be. However, when setting permittedArrowDirections to .top/.bottom, the problem goes away. Please see graphic below:

popover issue

I set up the popover as follows:

let popoverController = colorPickerVC.popoverPresentationController
popoverController!.permittedArrowDirections = .right
popoverController!.sourceRect = CGRect(x: Constants.uiPopoverArrowHorizontallOffset2, y: self.buttonLayersPicker.frame.height/2 ,width: 0,height: 0) // anchor popover to middle-left of calling button
popoverController?.backgroundColor = Constants.uiColorPopupBgDark1 // set the color of the popover arrow
    popoverController?.passthroughViews = [viewControllerMain.view] // allow interaction with bg view while popover is being displayed
// present popover
viewControllerMain.present(colorPickerVC, animated: true, completion: nil)

Has anyone come up against this issue? How to resolve?

Thanks in advance


Solution

  • This is not specific to Swift 5. This is a change in iOS 13. The area taken up by the popover arrow is now part of the view's frame. The solution is to make sure you base your layout on the view's safe area. In other words setup the constraints of the subviews against the view controller's view's safeAreaLayoutGuide.

    By using the safe area, your layout will be correct no matter where the popover arrow is located and it will work even if you support iOS 11 or 12 in addition to 13.