iOS9 popover始终指向锚点的左上角

时间:2015-09-19 08:51:46

标签: ios uiview uikit

我正在使用一个故事板segue,它将视图控制器显示为popover。该seque具有自定义UIView作为其锚点。在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;
     }
    ...
 }

示例:'短'按钮触发弹出窗口,弹出窗口指向'排序'控件的左上角

Resulting popover

Segue settings

9 个答案:

答案 0 :(得分:32)

我遇到了完全相同的问题。我刚刚通过在prepareForSegue中设置sourceRect来解决它:

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
    }
}

答案 1 :(得分:18)

有同样的问题,但我的应用程序有很多弹出窗口,所以我为修复程序创建了一个集中的功能(但仍然必须在每个具有弹出窗口的视图控制器上使用它)。

// 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 }   
   }       
}

答案 2 :(得分:8)

这是Igor Camilo在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;
        }
    }
}

答案 3 :(得分:7)

这是我在prepareForSegue内的解决方案:

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

这会将指针移动到锚视图的底部中间

答案 4 :(得分:1)

我也遇到过这个问题,但是当我将其添加到 PrepareForSegue 函数时,它现在可以正常工作了。鉴于我的Segue ID包含字符串 Popover

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

答案 5 :(得分:0)

如果您在主UIViewController中引用了弹出窗口UIViewController,则可以调整sourceRect属性以抵消弹出窗口。例如,给定popover popoverVC你可以这样做:

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

答案 6 :(得分:0)

尝试设置源矩形(UIView或UIBarButtonItem)的宽度和高度锚点并将其设置为活动状态。在初始化UIView或UIBarButtonItem时设置它。

<强>的UIBarButtonItem

 [[youruibarbuttonitem.customView.widthAnchor constraintEqualToConstant:youruibarbuttonitem.customView.bounds.size.width] setActive:YES];
 [[youruibarbuttonitem.customView.heightAnchor constraintEqualToConstant:youruibarbuttonitem.customView.bounds.size.height] setActive:YES];

<强>的UIView

[[uiview.widthAnchor constraintEqualToConstant:uiview.bounds.size.width] setActive:YES];
 [[uiview.heightAnchor constraintEqualToConstant:uiview.bounds.size.height] setActive:YES];

答案 7 :(得分:0)

Swift 3的一些更新答案!原谅所有的铸造

public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseKestrel()
            .UseUrls("http://*:54662")
            .Build();
}

答案 8 :(得分:0)

仅使用任何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
    }

}