IOS9 popover всегда указывает на верхний левый угол привязки

Я использую раскладку segue, которая представляет контроллер представлений как popover. Сек имеет собственный UIView как его якорь. На pre-iOS9 popover будет правильно указывать на центральное дно пользовательского UIView (представленного ниже UIView). На iOS9 он указывает на верхний левый угол UIView.

Я попытался проследить все вызовы селектора на пользовательский UIView, чтобы узнать, есть ли что-нибудь, что мне может понадобиться реализовать в моем настраиваемом UIView, чтобы предоставить "горячую точку" для popover, но не смог найти ничего

Любые идеи..? Благодаря

Благодаря @Igor Camilo его ответ - в случае, если это полезно для некоторых, вот как я исправил это в своем коде:

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

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

Пример: Кнопка "Короткие" запускает popover, popover указывает на верхний левый угол элемента "Сортировка"

Результат popover

Настройки Segue

Ответ 1

У меня была такая же проблема. Я просто решил это, установив sourceRect в 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
    }
}

Ответ 2

У той же проблемы, но у моего приложения множество всплывающих окон, поэтому я создал централизованную функцию для исправления (но все равно пришлось использовать ее на каждом контроллере представления, который имел pop).

// 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 sourceRect is not being set
//   so, if it is empty  CGRect(0,0,0,0), we simply set it to the source view 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 }   
   }       
}

Ответ 3

Вот пример фрагмента Игоря Камило в 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 bounds
            popoverPresentationController.sourceRect = ((UIView *)sender).bounds;
        }
    }
}

Ответ 4

Здесь мое решение внутри prepareForSegue:

segue.destinationViewController.popoverPresentationController?.sourceRect = CGRectMake(anchorView.frame.size.width/2, anchorView.frame.size.height, 0, 0)

Это переместит указатель на нижнюю середину представления привязки

Ответ 5

Я также столкнулся с этой проблемой, но теперь она работает, когда я добавил ее в мою функцию PrepareForSegue. Учитывая, что мой идентификатор Segue содержит строку Popover

if ([[segue identifier] containsString:@"Popover"]) {
    [segue destinationViewController].popoverPresentationController.sourceRect = self.navigationItem.titleView.bounds;
}

Ответ 6

Если вы ссылаетесь на свой popover UIViewController в своем основном UIViewController, вы можете настроить свойство sourceRect для смещения popover. Например, с учетом popover popoverVC вы можете сделать что-то вроде этого:

float xOffset = 10.0;
float yOffset = 5.0;
popoverVC.popoverPresentationController.sourceRect = CGMakeRect(xOffset, yOffset, 0.0, 0.0);