iOS9 popover always points to top-left corner of a

2019-03-17 05:14发布

I'm using a storyboard segue that presents a view controller as popover. The seque has a custom UIView as its anchor. On pre-iOS9 the popover would correctly point to the centre-bottom of the custom UIView (presented below the UIView). On iOS9 it points to the top-left corner of the UIView.

I did try to trace all selector calls to the custom UIView to find out if there is anything I may need to implement in my custom UIView to provide the 'hotspot' for the popover but couldn't find anything

Any ideas..? Thanks

Thanks to @Igor Camilo his reply - in case it's useful to some, this is how I fixed this in my code:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

     UIPopoverPresentationController* possiblePopOver = segue.destinationViewController.popoverPresentationController;
     if (possiblePopOver != nil) {
         //
         // iOS9 -- ensure correct sourceRect
         //
         possiblePopOver.sourceRect = possiblePopOver.sourceView.bounds;
     }
    ...
 }

Example: 'Short' button triggers a popover, the popover points to the top-left corner of 'Sort' control

Resulting popover

Segue settings

标签: ios uiview uikit
9条回答
干净又极端
2楼-- · 2019-03-17 06:09

A bit of a more updated answer for Swift 3! Pardon all the casting

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "popSegue" {
            let popoverViewController = segue.destination
            popoverViewController.popoverPresentationController?.delegate = self
            segue.destination.popoverPresentationController?.sourceRect = ((sender as? UIButton)?.bounds)!
        }
    }
查看更多
我想做一个坏孩纸
3楼-- · 2019-03-17 06:11

just to update to an actual example with working code for any UIView

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch segue.identifier {
    case "PopoverSegueId"?:
        if #available(iOS 9.0, *) {
            segue.destination.popoverPresentationController?.sourceRect = (segue.destination.popoverPresentationController?.sourceView?.bounds)!
        }
    default:
        break
    }

}
查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-03-17 06:19

Had the same issue but my app has a multitude of pop-over so I created a centralized function for the fix (but still had to use it on every view controller that had pop overs).

// Fix for IOS 9 pop-over arrow anchor bug
// ---------------------------------------
// - IOS9 points pop-over arrows on the top left corner of the anchor view
// - It seems that the popover controller's sourceRect is not being set
//   so, if it is empty  CGRect(0,0,0,0), we simply set it to the source view's bounds
//   which produces the same result as the IOS8 behaviour.
// - This method is to be called in the prepareForSegue method override of all
//   view controllers that use a PopOver segue
//
//   example use:
//
//          override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
//          {
//             fixIOS9PopOverAnchor(segue)   
//          }
//      
extension UIViewController
{
   func fixIOS9PopOverAnchor(segue:UIStoryboardSegue?)
   {
      guard #available(iOS 9.0, *) else { return }          
      if let popOver = segue?.destinationViewController.popoverPresentationController,
         let anchor  = popOver.sourceView
         where popOver.sourceRect == CGRect()      
            && segue!.sourceViewController === self 
      { popOver.sourceRect = anchor.bounds }   
   }       
}
查看更多
登录 后发表回答