在ios中创建自定义标注

时间:2014-01-02 15:54:11

标签: ios cocoa-touch mkmapview mkannotationview

我想在地图上创建自定义标注。我现在试过这个 -

    -(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
    NSLog(@"ANNNOTATION VIEW : %@", view);
    NSLog(@"VIEW ANNOTATION: %@", view.annotation);
    MyMapAnnotationViewController* mapAnnotationViewController = [[MyMapAnnotationViewController alloc]initWithNibName:@"MapAnnotationView" bundle:nil];
    MyLocation* location = (MyLocation*)view.annotation;
    [mapAnnotationViewController setTitle: [location title]];
    [mapAnnotationViewController setRating:3.0];
    [view addSubview:mapAnnotationViewController.view];   
}

-(void)viewWillAppear:(BOOL)animated{
    [_mapView setRegion: _viewRegion];
    for (id<MKAnnotation> annotation in _mapView.annotations) {
        [_mapView removeAnnotation:annotation];
    }
    for(NSDictionary* result in _resultsToPlot){
        NSString* address = someAddr;
        NSString* restaurantTitle = someTitle;
        NSString* description = someDescription;
        NSString* lonLat = someLonLat;
        NSArray *list = [lonLat componentsSeparatedByString:@";"];
        CLLocationCoordinate2D coordinate;
        coordinate.longitude = [[list objectAtIndex: 1] doubleValue];
        coordinate.latitude = [[list objectAtIndex: 0] doubleValue];
        MyLocation *annotation = [[MyLocation alloc] initWithName:restaurantTitle address:address coordinate:coordinate] ;

        [_mapView addAnnotation:annotation];
    }

MyLocation是MKAnnotation的子类。

然而,当我点击 -

时,这就是现在的样子

enter image description here

因此,当我点击一个图钉时,我的自定义视图显示AND注释显示。我只想要显示自定义视图。此外,当我点击另一个图钉时,之前的自定义视图仍然存在。

如何获取它以使注释成为我的自定义视图?

好的 - 所以我做了以下并添加了这个 -

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(MKAnnotationView*)annotation{
    annotation.canShowCallout = NO;
    return annotation;
}

我现在收到此错误 -

NSInvalidArgumentException', reason: '-[MyLocation setCanShowCallout:]: unrecognized selector sent to instance 0xcb683e0'

1 个答案:

答案 0 :(得分:2)

要禁止显示内置标注,请在canShowCallout委托方法的NO / MKPinAnnotationView上将MKAnnotationView设置为viewForAnnotation

下一个问题是,目前代码始终会创建一个 new 自定义标注视图,并将其添加到选定的注释视图中。这就是为什么你同时显示多个标注(之前选择的注释中的标注没有被删除)。

一种解决方案是保留自定义标注视图的单个实例,而不是每次选择注释时都创建一个新实例。然后,只需在选择或取消选择注释时添加/删除标注视图。

在包含地图视图的视图控制器中将此单个实例声明为强属性:

@property (nonatomic, strong) MyMapAnnotationViewController* mapAnnotationViewController;

viewDidLoad(或viewWillAppear中创建标注实例,如果它适合您),但不要在此时将其添加为子视图 - 只需创建它:

self.mapAnnotationViewController = [[MyMapAnnotationViewController alloc...

didSelectAnnotationView中,不要创建新的callout视图实例,而是告诉现有实例将其自身从当前的superview(如果有)中删除,然后将其添加到新注释的视图中:

-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
    NSLog(@"ANNNOTATION VIEW : %@", view);
    NSLog(@"VIEW ANNOTATION: %@", view.annotation);

    [self.mapAnnotationViewController.view removeFromSuperview];

    MyLocation* location = (MyLocation*)view.annotation;
    [self.mapAnnotationViewController setTitle: [location title]];
    [self.mapAnnotationViewController setRating:3.0];
    //Since we are re-using the callout view, 
    //may need to do additional "cleanup" so that the callout
    //shows the new annotation's data.

    [view addSubview:self.mapAnnotationViewController.view];   
}

最后,您需要处理用户通过点击地图(而不是其他注释)取消选择注释并只删除标注视图的情况:

-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
    [self.mapAnnotationViewController.view removeFromSuperview];
}


viewForAnnotation委托方法应如下所示:

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    if (! [annotation isKindOfClass:[MyLocation class]])
    {
        //tell map view to show default view for annotations other than ours
        //(like the user location blue dot)
        return nil;
    }

    MKPinAnnotationView *pav = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"pin"];
    if (pav == nil)
    {
        pav = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"pin"];
        pav.canShowCallout = NO;
    }
    else
    {
        pav.annotation = annotation;
    }

    return pav;
}