如何将UIBezierPath引入MKAnnotation对象的后面?

时间:2013-02-05 18:30:24

标签: ios objective-c mkmapview uibezierpath

在我的应用中,用户在地图上绘制一个形状并使用UIBeizerPath我正在绘制该路径。然后根据路径的坐标我显示仅在该区域的结果。一切都很好,除了现在当注释在地图视图上掉落时,引脚看起来就像它们在路径后面,这意味着路径在前面看起来。

我正在使用此代码显示注释和路径:

 -(void)clearAnnotationAndPath:(id)sender {
    [_mapView removeAnnotations:_mapView.annotations];
    path = [UIBezierPath bezierPath];
    [shapeLayer removeFromSuperlayer];
}

- (void)handleGesture:(UIPanGestureRecognizer *)gesture
{

    CGPoint location = [gesture locationInView:_pathOverlay];

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        shapeLayer = [[CAShapeLayer alloc] init];
        shapeLayer.fillColor = [[UIColor clearColor] CGColor];
        shapeLayer.strokeColor = [[UIColor greenColor] CGColor];
        shapeLayer.lineWidth = 5.0;
        //[_mapView.layer addSublayer:shapeLayer];
        [pathOverlay.layer addSublayer:shapeLayer];
        path = [UIBezierPath bezierPath];
        [path moveToPoint:location];
    }

    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        [path addLineToPoint:location];
        shapeLayer.path = [path CGPath];
    }

    else if (gesture.state == UIGestureRecognizerStateEnded)
    {
        // MKMapView *mapView = (MKMapView *)gesture.view;

        [path addLineToPoint:location];
        [path closePath];
        allStations = [RoadmapData sharedInstance].data;
        for (int i=0; i<[allStations count]; i++) {
            NSDictionary * itemNo = [allStations objectAtIndex:i];

            NSString * fullAddress = [NSString stringWithFormat:@"%@,%@,%@,%@",[itemNo objectForKey:@"address"],[itemNo objectForKey:@"city"],[itemNo objectForKey:@"state"],[itemNo objectForKey:@"zip"]];
            CLGeocoder * geoCoder = [[CLGeocoder alloc]init];
            [geoCoder geocodeAddressString:fullAddress completionHandler:^(NSArray *placemarks, NSError *error) {

                if (error) {
                    NSLog(@"Geocode failed with error: %@", error);
                    return;
                }

                if(placemarks && placemarks.count > 0)
                {
                    CLPlacemark *placemark = placemarks[0];
                    CLLocation *location = placemark.location;
                    CLLocationCoordinate2D coords = location.coordinate;
                    CGPoint loc = [_mapView convertCoordinate:coords toPointToView:_pathOverlay];
                    if ([path containsPoint:loc])
                    {
                        NSString * name = [itemNo objectForKey:@"name"];
                        stationAnn = [[LocationAnnotation alloc]initWithCoordinate:coords Title:name subTitle:@"Wells Fargo Offer" annIndex:i];
                        stationAnn.tag = i;
                        [_mapView addAnnotation:stationAnn];
                    }
                    else{
                        NSLog(@"Out of boundary");
                    }
                }
            }];
            [self turnOffGesture:gesture];
        }
    }
}

- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views{
    if (views.count > 0) {
        UIView* firstAnnotation = [views objectAtIndex:0];
        UIView* parentView = [firstAnnotation superview];
        if (_pathOverlay == nil){
            // create a transparent view to add bezier paths to
            pathOverlay = [[UIView alloc] initWithFrame: parentView.frame];
            pathOverlay.opaque = NO;
            pathOverlay.backgroundColor = [UIColor clearColor];
            [parentView addSubview:pathOverlay];
        }

        // make sure annotations stay above pathOverlay
        for (UIView* view in views) {
            [parentView bringSubviewToFront:view];
        }
    }
}

此外,一旦我从这里回来并再次看到它甚至没有绘制路径。

请帮忙。

谢谢,

1 个答案:

答案 0 :(得分:3)

显然,当您通过以下方式将贝塞尔曲线路径添加到地图时

        [_mapView.layer addSublayer:shapeLayer];

正在添加 某个MKMapView用于绘制注释的内部图层。如果you take a look at this somewhat related question,您将看到可以实施MKMapViewDelegate协议,并在添加新的工作站注释时获得回调。发生这种情况时,您基本上检查新添加的注释的视图层次结构,并在它们下面插入一个新的透明UIView 。您需要注意将所有注释带到此透明UIView前面。

  // always remember to assign the delegate to get callbacks!
  _mapView.delegate = self;

...

#pragma mark - MKMapViewDelegate

- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views{
    if (views.count > 0) {
        UIView* firstAnnotation = [views objectAtIndex:0];
        UIView* parentView = [firstAnnotation superview];
        // NOTE: could perform this initialization in viewDidLoad, too
        if (self.pathOverlay == nil){
            // create a transparent view to add bezier paths to
            pathOverlay = [[UIView alloc] initWithFrame: parentView.frame];
            pathOverlay.opaque = NO;
            pathOverlay.backgroundColor = [UIColor clearColor];
            [parentView addSubview:pathOverlay]; 
        }

        // make sure annotations stay above pathOverlay
        for (UIView* view in views) {
            [parentView bringSubviewToFront:view];
        }
    }
}

然后,不是将形状图层添加到_mapView.layer,而是将其添加到透明视图图层,也可以在坐标转换中使用此新图层:

- (void)handleGesture:(UIPanGestureRecognizer*)gesture
{
    CGPoint location = [gesture locationInView: self.pathOverlay];

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        if (!shapeLayer)
        {
            shapeLayer = [[CAShapeLayer alloc] init];
            shapeLayer.fillColor = [[UIColor clearColor] CGColor];
            shapeLayer.strokeColor = [[UIColor greenColor] CGColor];
            shapeLayer.lineWidth = 5.0;
            [pathOverlay.layer addSublayer:shapeLayer];   // <- change here !!!
        }
        self.path = [[UIBezierPath alloc] init];
        [path moveToPoint:location];
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        [path addLineToPoint:location];
        shapeLayer.path = [path CGPath];
    }
    else if (gesture.state == UIGestureRecognizerStateEnded)
    {
        /*
         * This code is the same as what you already have ...
         */

             // But replace this next line with the following line ...
             //CGPoint loc = [_mapView convertCoordinate:coords toPointToView:self];
             CGPoint loc = [_mapView convertCoordinate:coords toPointToView: self.pathOverlay];

        /*
         * And again use the rest of your original code
         */            
    }
}

我还为新的透明层添加了 ivar (和属性):

UIView* pathOverlay;

我用一个虚假的站点网格对此进行了测试,得到了以下结果:

enter image description here

P.S。我还建议您删除static个变量。只要让它们成为你班级的ivars /属性。