I did a little digging on this, to figure out how it is being solved by other developers.
First, though this would appear to many to be a bug, it actually puts the popover presentation view controller in line with how view controllers work in general. Since iOS 11+ Apple has provided a "safe area" concept which is supposed to be used by the view hierarchy to indicate what part of their content area is obscured. In the case of the popover view controller, the arrow is still part of the content area, but it obscures content.
@cvp, @mikael you are both the dudes!
I'm providing a somewhat more complex but general way below, which doesn't suffer from the delay between presentation of the popover and content. The trouble is that the safeAreaInsets() is always 0 before a view is displayed, so it can't be used to set the proper location of a view before it is visible. However, using the safeAreaLayoutGuide() and the constraint/anchor system, the content view can be made to size itself automatically to the safe area:
import ui
def present_popup(content_view, position):
popup = ui.View(
width=content_view.width,
height=content_view.height,
)
popup.add_subview(content_view)
content_view.objc_instance.translatesAutoresizingMaskIntoConstraints = False
guide = popup.objc_instance.safeAreaLayoutGuide()
anchor = content_view.objc_instance.leadingAnchor()
anchor.constraintEqualToAnchor_(guide.leadingAnchor()).active = True
anchor = content_view.objc_instance.trailingAnchor()
anchor.constraintEqualToAnchor_(guide.trailingAnchor()).active = True
anchor = content_view.objc_instance.topAnchor()
anchor.constraintEqualToAnchor_(guide.topAnchor()).active = True
anchor = content_view.objc_instance.bottomAnchor()
anchor.constraintEqualToAnchor_(guide.bottomAnchor()).active = True
popup.present(style="popover",
popover_location=position,
hide_title_bar=True)
return popup
if __name__ == '__main__':
popup_content = ui.Label(
text="Hello!",
border_width=3,
frame=(0,0,150,100),
)
popup = present_popup(popup_content, (100, 100))