iOS9 popover always points to top-left corner of anchor
I had the exact same problem. I just resolved it by setting sourceRect in prepareForSegue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { switch segue.identifier { case "Popover Identifier"?: if #available(iOS 9.0, *) { segue.destinationViewController?.popoverPresentationController?.sourceRect = anchorView.bounds } default: break }}
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 } } }
Here's an example of Igor Camilo's snippet in Objective-C.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ // If the sender is a UIView, we might have to correct the sourceRect of // a potential popover being presented due to an iOS 9 bug. See: // https://openradar.appspot.com/22095792 and http://stackoverflow.com/a/32698841/368674 if ([sender isKindOfClass:UIView.class]) { // Fetch the destination view controller UIViewController *destinationViewController = [segue destinationViewController]; // If there is indeed a UIPopoverPresentationController involved if ([destinationViewController respondsToSelector:@selector(popoverPresentationController)]) { // Fetch the popover presentation controller UIPopoverPresentationController *popoverPresentationController = destinationViewController.popoverPresentationController; // Set the correct sourceRect given the sender's bounds popoverPresentationController.sourceRect = ((UIView *)sender).bounds; } }}