【问题标题】:Creating a custom callout in ios在 ios 中创建自定义标注
【发布时间】:2014-01-02 15:54:11
【问题描述】:

我想在我的地图上创建自定义标注。我现在已经试过了-

    -(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 的子类。

但是,当我单击时,这就是现在的样子 -

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

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

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

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

我现在收到此错误-

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

【问题讨论】:

    标签: ios cocoa-touch mkmapview mkannotationview


    【解决方案1】:

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

    下一个问题是当前代码总是创建一个 new 自定义标注视图并将其添加到所选注释的视图中。这就是为什么您会同时显示多个标注(之前选择的注释上的标注不会被删除)。

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

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

    @property (nonatomic, strong) MyMapAnnotationViewController* mapAnnotationViewController;
    

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

    self.mapAnnotationViewController = [[MyMapAnnotationViewController alloc...
    

    didSelectAnnotationView 中,不是创建一个新的标注视图实例,而是告诉现有实例从其当前超级视图(如果有)中删除自己,然后将其添加到新注释的视图中:

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

    【讨论】:

    • 所以 viewForAnnotation 方法给了我一个 ,而不是一个 MKAnnotationView - 你说的是那个方法吗?
    • 我将添加一个示例,说明viewForAnnotation 方法的外观。
    • 谢谢 - 我一直坚持这个问题,似乎有很多解决方案和很多代码
    • 注解的model对象是MKAnnotation类型,view对象是MKAnnotationView类型。在 viewForAnnotation 中,您为 model 创建并返回一个 view
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    相关资源
    最近更新 更多