我有一个可能绘制了数百个多边形的MKMapView。假设在iOS7上使用MKPolygon和MKPolygonRenderer作为之一。

我需要的是一种对用户触摸多边形之一起作用的方法。例如,它们代表 map 上具有一定人口密度的区域。
在iOS6上,MKOverlays被绘制为MKOverlayViews,因此触摸检测更加简单。现在使用渲染器,我真的不知道该如何完成。

我不确定这是否会有所帮助,甚至是否相关,但作为引用,我将发布一些代码:

这将使用mapData将所有MKOverlays添加到MKMapView。

-(void)drawPolygons{
    self.polygonsInfo = [NSMutableDictionary dictionary];
    NSArray *polygons = [self.mapData valueForKeyPath:@"polygons"];

    for(NSDictionary *polygonInfo in polygons){
        NSArray *polygonPoints = [polygonInfo objectForKey:@"boundary"];
        int numberOfPoints = [polygonPoints count];

        CLLocationCoordinate2D *coordinates = malloc(numberOfPoints * sizeof(CLLocationCoordinate2D));
        for (int i = 0; i < numberOfPoints; i++){
            NSDictionary *pointInfo = [polygonPoints objectAtIndex:i];

            CLLocationCoordinate2D point;
            point.latitude = [[pointInfo objectForKey:@"lat"] floatValue];
            point.longitude = [[pointInfo objectForKey:@"long"] floatValue];

            coordinates[i] = point;
        }

        MKPolygon *polygon = [MKPolygon polygonWithCoordinates:coordinates count:numberOfPoints];
        polygon.title = [polygonInfo objectForKey:@"name"];
        free(coordinates);
        [self.mapView addOverlay:polygon];
        [self.polygonsInfo setObject:polygonInfo forKey:polygon.title]; // Saving this element information, indexed by title, for later use on mapview delegate method
    }
}

然后是用于为每个MKOverlay返回MKOverlayRenderer的委托(delegate)方法:
-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
    /* ... */

    MKPolygon *polygon = (MKPolygon*) overlay;
    NSDictionary *polygonInfo = [self.polygonsInfo objectForKey:polygon.title]; // Retrieving element info by element title
    NSDictionary *colorInfo = [polygonInfo objectForKey:@"color"];

    MKPolygonRenderer *polygonRenderer = [[MKPolygonRenderer alloc] initWithPolygon:polygon];

    polygonRenderer.fillColor = [UIColor colorWithRed:[[colorInfo objectForKey:@"red"] floatValue]
                                               green:[[colorInfo objectForKey:@"green"] floatValue]
                                                blue:[[colorInfo objectForKey:@"blue"] floatValue]
                                               alpha:[[polygonInfo objectForKey:@"opacity"] floatValue]];

    return polygonRenderer;

    /* ... */
}

最佳答案

我做完了

感谢 incanus Anna !

基本上,我将TapGestureRecognizer添加到MapView,将点击的点转换为 map 坐标,浏览我的叠加层并使用CGPathContainsPoint进行检查。

添加TapGestureRecognizer。我做了增加第二个双击手势的技巧,以便在双击 map 时不会触发单击手势。如果有人知道更好的方法,我很高兴听到!

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapTap:)];
tap.cancelsTouchesInView = NO;
tap.numberOfTapsRequired = 1;

UITapGestureRecognizer *tap2 = [[UITapGestureRecognizer alloc] init];
tap2.cancelsTouchesInView = NO;
tap2.numberOfTapsRequired = 2;

[self.mapView addGestureRecognizer:tap2];
[self.mapView addGestureRecognizer:tap];
[tap requireGestureRecognizerToFail:tap2]; // Ignore single tap if the user actually double taps

然后,在点击处理程序上:
-(void)handleMapTap:(UIGestureRecognizer*)tap{
    CGPoint tapPoint = [tap locationInView:self.mapView];

    CLLocationCoordinate2D tapCoord = [self.mapView convertPoint:tapPoint toCoordinateFromView:self.mapView];
    MKMapPoint mapPoint = MKMapPointForCoordinate(tapCoord);
    CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y);

    for (id<MKOverlay> overlay in self.mapView.overlays) {
        if([overlay isKindOfClass:[MKPolygon class]]){
            MKPolygon *polygon = (MKPolygon*) overlay;

            CGMutablePathRef mpr = CGPathCreateMutable();

            MKMapPoint *polygonPoints = polygon.points;

            for (int p=0; p < polygon.pointCount; p++){
                MKMapPoint mp = polygonPoints[p];
                if (p == 0)
                    CGPathMoveToPoint(mpr, NULL, mp.x, mp.y);
                else
                    CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y);
            }

            if(CGPathContainsPoint(mpr , NULL, mapPointAsCGP, FALSE)){
                // ... found it!
            }

            CGPathRelease(mpr);
        }
    }
}

我可以要求已经具有“path”属性的MKPolygonRenderer并使用它,但是由于某些原因,它始终为nil。我确实读过别人的话,说我可以在渲染器上调用invalidatePath,它确实填充了path属性,但由于在任何多边形内都找不到该点,因此这似乎是错误的。这就是为什么我要从各个角度重建路径。这样,我什至不需要渲染器,而只使用MKPolygon对象。

关于ios - 在iOS7中检测MKOverlay的触摸(MKOverlayRenderer),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20858108/

10-09 01:03
查看更多