【问题标题】:Detecting a point in a MKPolygon broke with iOS7 (CGPathContainsPoint)检测 MKPolygon 中的一个点与 iOS7 (CGPathContainsPoint) 冲突
【发布时间】:2013-09-25 20:48:53
【问题描述】:

在今年早些时候我问过的SO question 中,我得到了这段代码:

MKPolygonView *polygonView = (MKPolygonView *)[self.mapView viewForOverlay:polygon];
MKMapPoint mapPoint = MKMapPointForCoordinate(tapCoord);
CGPoint polygonViewPoint = [polygonView pointForMapPoint:mapPoint];

if (CGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, FALSE)) {
    // do stuff
}

这在 iOS7 之前运行良好。它现在总是返回 false 并且不会检测到路径中的点。

我正在尝试查找任何说明方法更改的文档,但找不到任何文档。

任何想法为什么它坏了?还是新的解决方案?

【问题讨论】:

    标签: ios objective-c mkmapview mapkit


    【解决方案1】:

    由于某种原因(可能是一个错误),path 属性在当前版本的 iOS 7 中返回 NULL

    一种解决方法是从多边形的points 构造您自己的CGPathRef
    使用此方法,您不需要引用MKPolygonViewMKPolygonRenderer

    例如:

    CGMutablePathRef mpr = CGPathCreateMutable();
    
    MKMapPoint *polygonPoints = myPolygon.points;
    //myPolygon is the MKPolygon
    
    for (int p=0; p < myPolygon.pointCount; p++)
    {
        MKMapPoint mp = polygonPoints[p];
        if (p == 0)
            CGPathMoveToPoint(mpr, NULL, mp.x, mp.y);
        else
            CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y);
    }
    
    CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y);
    //mapPoint above is the MKMapPoint of the coordinate we are testing.
    //Putting it in a CGPoint because that's what CGPathContainsPoint wants.
    
    BOOL pointIsInPolygon = CGPathContainsPoint(mpr, NULL, mapPointAsCGP, FALSE);
    
    CGPathRelease(mpr);
    

    这应该也适用于 iOS 6。
    但是,您可能希望仅在覆盖视图的 path 属性返回 NULL 时才进行此手动构造。

    【讨论】:

    • 请注意:如果MKPolygon 不可见,polygon.path 属性将在 iOS 6 中返回 NULL。这个解决方案就像一个魅力,非常感谢女士安娜!
    • 这很好用。注意:“CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y);”这一行很关键;我的代码以前这样做过“CGPoint polygonViewPoint = [overlayView pointForMapPoint:mapPoint];”这似乎在 iOS7 中也被破坏了。
    • @sethpollack:mapPointAsCGP 的事情只是为了避免可能的编译器警告,即您正在传递一个 MKMapPoint 预期 CGPoint (它不会更改传递的值 - 它只是将它们在 CGPoint 结构内)。 pointForMapPoint 在这里不起作用的原因是路径是使用 MKMapPoint 单位构建的,所以我们正在测试的点也必须是 MKMapPoint 单位(不是实际的屏幕 CGPoint 单位)。
    • @Anna - 我正在尝试测试现有的地图注释以查看它们是否在多边形内。关于将注释转换为 CGPoint 以进行此评估的任何提示?以前的参考使用 [polygon pointForMapPoint:point]。提前致谢!
    • @CocoaEv:如代码示例中所述://mapPoint above is the MKMapPoint of the coordinate we are testing. 因此,您将注释的coordinate 使用MKMapPointForCoordinate 函数将其转换为MKMapPoint。所有“CG”的东西只是因为我们使用的是核心图形函数(不是实际的 CGPoints)。
    【解决方案2】:

    我遇到了同样的问题。通过在访问路径之前调用 MKPolygonRenderer 上的 invalidatePath 来解决它。

    【讨论】:

      【解决方案3】:

      你的代码的问题在于方法

      - (MKOverlayView *)viewForOverlay:(id < MKOverlay >)overlay
      

      已在 iOS 7 (See the doc) 中弃用,您应该改为 use this

      - (MKOverlayRenderer *)rendererForOverlay:(id < MKOverlay >)overlay
      

      所以,为了让您的代码在 iOS 7 中正常工作,您必须更换:

      MKPolygonView *polygonView = (MKPolygonView *)[self.mapView viewForOverlay:polygon];
      

      MKPolygonRenderer *polygonView = (MKPolygonRenderer *)[self.mapView rendererForOverlay:polygon];
      

      问题在于 - rendererForOverlay: 是 iOS 7 中的新功能,因此此更改使您的应用程序无法在以前的版本中运行。您可以实现两个版本的方法并根据 iOS 版本调用其中一个或另一个。

      与@Anna 解决方案相比,我没有对其性能进行分析

      【讨论】:

      • 问题是 MKPolygonView/MKPolygonRenderer 的 path 属性在 iOS 7 中返回 null(即使使用 rendererForOverlay)。根据您的经验,path 在调用 rendererForOverlay 后是否在 MKPolygonRenderer 中有值?
      • 是的,在我的情况下使用rendererForOverlay 路径返回一个非空值,除非作为参数发送的polygon 之前没有添加到mapView 中
      【解决方案4】:

      它在 7.1 上直接运行,但在 7.0 上不运行。

      jdehlin 响应为我解决了 7.0 的问题,即。在每次调用之前调用[view invalidatePath]

      CGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, FALSE)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多