【问题标题】:MKMapview annotation dynamic pin image changes after zoomingMKMapview注解动态pin图缩放后变化
【发布时间】:2013-05-10 22:48:36
【问题描述】:

我正在做一个小项目,在地图上显示 7 种不同类型的注释。我的注释取自数组中的 url 结果,我使用 JSON 对其进行解析。我有很多注释,一旦地图加载,一切看起来都很好。放大和缩小后,pin 图像由于某种原因变为错误的 pin 图像(特定图像,不知道为什么)。

我确定我在这里遗漏了一些东西...请您帮忙 :) 吗?

这是我的代码的一部分,如果您需要,请告诉我:

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{

static NSString *identifier;

if(_mapView.tag==1){identifier = @"TurbulencePin";}
if(_mapView.tag==2){identifier = @"IcingPin";}
if(_mapView.tag==3){identifier = @"WindsPin";}
if(_mapView.tag==4){identifier = @"TemperaturePin";}
if(_mapView.tag==5){identifier = @"CloudsPin";}
if(_mapView.tag==6){identifier = @"VisibilityPin";}
if(_mapView.tag==7){identifier = @"MultiplePin";}


if ([annotation isKindOfClass:[MKUserLocation class]])
    return nil;

if ([annotation isKindOfClass:[Annotation class]]) {

    CustomAnnotationView* annotationView = (CustomAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
    annotationView = nil;

    if (annotationView == nil) {

        annotationView = [[CustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
        annotationView.enabled = YES;
        annotationView.canShowCallout = YES;


        UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:@"%@.png",identifier]];
        annotationView.image = img;

    }
else
    {

        annotationView.annotation = annotation;

    }


    return annotationView;

}
return nil;

}

更新:

根据其他人的反馈,我将图片设置的代码修改如下:

 Annotation *myCustomAnn = (Annotation *)annotation;
 NSString *imgName = myCustomAnn.imageName;
 UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:@"%@Pin.png",imgName]];
 annotationView.image = img;

 return annotationView;

另外,我删除了annotationView = nil;

但是,我无法将 annotation.m 中的图像名称设置为硬编码值,因为我需要为每个注释显示不同的 pin 图像。我确定有一个解释,但我可以从 mapView:viewForAnnotation: 下的 annotation.m 获得的唯一值是注释坐标(myCustomAnn.coordinate.latitudemyCustomAnn.coordinate.longitude),我不知道如何获取其他属性来自注解.m

其他属性,如title、imgname等返回为null

【问题讨论】:

  • 这个注解类型应该是注解的一个属性,而不是使用地图的tag属性。 (顺便说一句,如果您以编程方式设置它,您的identifier 不需要是静态的。)但我能想象的唯一会导致图钉图像发生变化的是tag 是否以某种方式发生变化。我建议记录一下,看看发生了什么(但更好的是,放弃tag 并为您的注释使用自定义属性)。
  • 顺便说一句,我希望你不要同时打开七张地图。如果你这样做了,不要使用_mapView(这是一些ivar),而是使用mapView,这个方法的参数。
  • 您说“无法在 annotation.m 中设置图像名称 ...”。正确的。你不应该在 annotation.m 中这样做。在您的 annotation.h 中,您应该简单地为 imageName 定义一个新属性。然后在创建注释后创建注释的代码(您的视图控制器?)中,您可以在其中为注释设置 imageName 属性。关于您的其他属性为空,问题是您是否在您的 VC 中设置了这些属性,您在其中执行了注释对象的 alloc/init,但在您执行 addAnnotation 调用之前。
  • 我通过使用 JSON 解析许多注释的数组来提供注释属性。该数组包括每个注释的坐标、标题等。所以基本上,坐标和其余属性是同时设置的,我可以从 annotation.m 传递到 mapView:viewForAnnotation: 的唯一属性是坐标... :/ 我错过了什么和 Rob ,对于你的问题,不,我只使用一张地图
  • 在为该注记设置所有属性之前,您不应将该注记添加到您的地图中。 addAnnotation 应该是最后一步。或者,有时我会将注释添加到NSMutableArray,将它们调整到我心中的内容,然后,最后,我将使用addAnnotations(注意s),将它传递给我的数组.

标签: ios mapkit mkannotationview


【解决方案1】:

主要问题是viewForAnnotation中的代码依赖外部变量_mapView.tag来确定注解视图。

假设viewForAnnotation 委托方法何时以及多久被地图调用是不安全的。

如果注释的视图依赖于某些值,通常最好将这些值直接嵌入到注释对象本身中。这样,在viewForAnnotation 委托方法中,您可以通过传递给该方法的annotation 参数引用那些特定于注解的值。应该在创建注解时(在调用addAnnotation 之前)设置这些注解特定的值。

有关更多详细信息和示例,请参阅:

另一个问题是代码在调用dequeueReusableAnnotationViewWithIdentifier 后将annotationView 设置为nil,这会破坏出队。


至少在viewForAnnotation 中,处理Annotation 类的更正代码可能如下所示(不是整个方法——只是第二个if 中的部分):

static NSString *identifier = @"ann";

CustomAnnotationView* annotationView = (CustomAnnotationView*)[mapView 
    dequeueReusableAnnotationViewWithIdentifier:identifier];

//annotationView = nil;  // <-- remove this line

if (annotationView == nil) 
{
    annotationView = [[CustomAnnotationView alloc] 
                         initWithAnnotation:annotation 
                         reuseIdentifier:identifier];
    annotationView.enabled = YES;
    annotationView.canShowCallout = YES;
}
else
{
    annotationView.annotation = annotation;
}

//MOVE the setting of the image to AFTER the dequeue/create 
//because the image property of the annotation view 
//is based on the annotation and we can update image in one place
//after both the dequeue and create are done...

//Get the image name from the annotation ITSELF 
//from a custom property (that you add/set)
Annotation *myCustomAnn = (Annotation *)annotation;

NSString *imgName = myCustomAnn.imageName;  
//imageName is the custom property you added/set

UIImage *img = [UIImage imageNamed:
                   [NSString stringWithFormat:@"%@.png",imgName]];

annotationView.image = img;

return annotationView;

【讨论】:

  • 我同意使用注释属性。我会投票给enum 注释类型参数,而不是字符串的名称。而且我个人不介意 OP 为每种类型的注释视图使用自定义注释标识符(而不是不管你是否必须重置 image 属性)。另外,我认为 OP 的annotationView = nil 设置不是他的错误,而是一个故意的诊断过程,以暂时将dequeue... 逻辑排除在循环之外,从而简化问题。
  • @Rob,我同意你的所有观点。我的主要目的是指出外部变量的滥用。
  • 同意。当实际的mapView 传递给方法时,引用_mapView ivar 尤其令人好奇。回想起来,tag 的使用令人担忧,不仅因为您正确指出的原因,而且还可能暗示他同时打开了七个地图视图(这让我觉得是对系统资源的过度使用) . +1
【解决方案2】:

一个问题是viewForAnnotation 正在根据类实例变量确定要显示的正确图像。通常注释图像的标识符是自定义注释本身的属性,而不是某些外部实例变量。

最重要的是,似乎在设置所有注释的属性之前将注释添加到地图中。应该推迟addAnnotation,直到设置了所有注释的属性。

或者,您可以将注释添加到NSMutableArray,根据需要对其进行调整,然后仅在最后使用addAnnotations(注意s)添加注释,然后将其传递给数组。

【讨论】:

    【解决方案3】:

    由 Rob 解决

    问题是,我无法检索我在 VC 中设置的注释属性。原因是我在设置所有注释的属性之前使用了[_mapView addAnnotation:ann]; 命令。也就是说,通过将此行移动到注释初始属性设置的末尾部分,解决了问题。

    谢谢大家,非常感谢 Rob! 我已经准备好迎接下一个挑战了。

    【讨论】:

      猜你喜欢
      • 2011-11-15
      • 2010-11-14
      • 2013-09-29
      • 2011-06-08
      • 1970-01-01
      • 2011-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多