8

The popover that I display is now bad displayed. There is a line missing on the arrow side. We can check that there is a little piece of black just at the end of the arrow. I think there is a view inside that is too long.

Code to display the popover:

   _popoverController = UIPopoverController(contentViewController: navController)
   _popoverController?.delegate = self

   let rect = slotCollectionView.cellForItem(at: indexPath)!.frame
   self._popoverController?.backgroundColor = UIColor.init(rgb: Int(quaternaryColorHexa))
   self._popoverController?.present (from: rect, in: self.slotCollectionView, permittedArrowDirections: UIPopoverArrowDirection.any, animated: true) 

Code to init Popover:

override func viewDidLoad()
{
    super.viewDidLoad()

    self.preferredContentSize = contentSize()
    self.navigationController!.preferredContentSize = self.preferredContentSize;

    peopleTableView.isScrollEnabled = true
    peopleTableView.bounces = true
    peopleTableView.tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
    peopleTableView.tableFooterView?.isHidden = true
    peopleTableView.backgroundColor = UIColor.init(rgb: Int(quinquenaryColorHexa))

    self.view.backgroundColor = UIColor.init(rgb: Int(quinquenaryColorHexa))
    self.view.layer.cornerRadius = 13.0
    self.view.layer.borderWidth = 1.5
    self.view.layer.borderColor = UIColor.init(rgb: Int(quaternaryColorHexa)).cgColor 

iOS12 display:
iOS12
iOS13 display:
iOS13

ΩlostA
  • 2,501
  • 5
  • 27
  • 63
  • Probably, because it was [deprecated since iOS 9.0](https://developer.apple.com/documentation/uikit/uipopovercontroller) and Apple does not support API related to this UI component. Use another approach. – Aleksey Potapov Sep 10 '19 at 09:23
  • 1
    Same problem exists with more modern modalPresentationStyle = UIModalPresentationPopover; approach – Nikolay Klimchuk Sep 14 '19 at 02:48

4 Answers4

3

As mentioned in this answer it is a new feature of iOS 13 that UIPopovers include the arrows in their content views. You should use the safe area to properly react to this change.

alexkaessner
  • 1,966
  • 1
  • 14
  • 39
  • @iOSProgrammingIsFun When using auto layout, link your top view position to the top safe area layout guide instead of the superview. That should be enough. In case of the UITableView content/scroll inset: have you tried setting the tableViews inset to the views safe area? Maybe the `tableView.safeAreaInsets` ignore the popovers safe area. – alexkaessner Sep 29 '19 at 19:46
  • Here's some examples: https://stackoverflow.com/questions/58149863/ios13-uipopoverviewcontroller-showing-uitableviewcontroller-safe-area-problems it's my question about this. – iOSProgrammingIsFun Sep 29 '19 at 20:54
2

You cannot use the safe area to react to this change. My feeling is that this is a bug in iOS 13 and I'll explain why...

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.

2

I think it is an iOS bug in the iOS13 version, and I advice you to do your own popover by using that git project:
DDPopoverBackgroundView

and using this for displaying the popover:

       // Popover
       _popoverController = UIPopoverController(contentViewController: navController)
       _popoverController?.delegate = self

       let rect = slotCollectionView.cellForItem(at: indexPath)!.frame

       self._popoverController!.contentSize = CGSize(width: 350, height: 600)

       self._popoverController!.backgroundViewClass = DDPopoverBackgroundView.self
       self._popoverController!.backgroundColor = UIColor.init(rgb: Int(quaternaryColorHexa)) //arrow color

       OperationQueue.main.addOperation({
           self._popoverController?.present(from: rect, in: self.slotCollectionView, permittedArrowDirections: UIPopoverArrowDirection.any, animated: true)
       })

enjoy ! ;-)

WikeC
  • 131
  • 2
  • 10
2

I had the same issue. My solution was as follows:

class MyPopoverViewController: UIViewController {
    override func viewWillAppear(_ animated: Bool) {
        let borderColor = UIColor.black
        let borderWidth = CGFloat(1.5)
        let cornerRadius = CGFloat(13)
        let extensionWidth = CGFloat(20)

        if #available(iOS 13, *), let superview = self.view.superview {
            let guide = self.view.safeAreaLayoutGuide
            let borderView = UIView()
            borderView.isUserInteractionEnabled = false
            borderView.backgroundColor = UIColor.clear
            borderView.layer.borderWidth = borderWidth + extensionWidth
            borderView.layer.cornerRadius = cornerRadius + extensionWidth
            borderView.layer.borderColor = borderColor.cgColor
            borderView.translatesAutoresizingMaskIntoConstraints = false
            superview.addSubview(borderView)
            NSLayoutConstraint.activate([
                borderView.leftAnchor.constraint(equalTo: guide.leftAnchor, constant: -extensionWidth),
                borderView.topAnchor.constraint(equalTo: guide.topAnchor, constant: -extensionWidth),
                borderView.bottomAnchor.constraint(equalTo: guide.bottomAnchor, constant: extensionWidth),
                borderView.rightAnchor.constraint(equalTo: guide.rightAnchor, constant: extensionWidth)
            ])
        } else {
            self.view.layer.borderWidth = borderWidth
            self.view.layer.cornerRadius = cornerRadius
            self.view.layer.borderColor = borderColor.cgColor
            self.view.clipsToBounds = true
            self.popoverPresentationController?.backgroundColor = borderColor
        }
    }
}
jqgsninimo
  • 6,562
  • 1
  • 36
  • 30