地图注释从显示图像随机切换到默认图钉

Map annotation swapping from displaying image to default pin randomly

当通过模拟器测试地图时,我注意到一些注释显示默认图钉而不是自定义图像。当我返回应用程序主菜单并再次进入地图视图时,不同的注释会发生同样的事情。

这段代码展示了我拥有的 20 个注释中的 4 个,它们都使用相同的代码。

-(void)viewDidLoad {

[super viewDidLoad];

_locationManager = [[CLLocationManager alloc] init];
[mapView setDelegate:self];
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];

MKCoordinateRegion test1 = { {0.0, 0.0} , {0.0, 0.0} };
test1.center.latitude = 55.705609;
test1.center.longitude = 13.195707;
[mapView setRegion:test1 animated:YES];

testmap *ann2 = [[testmap alloc] init];
ann2.title = @"test1";
ann2.subtitle = @"Klicka här för mer info";
ann2.coordinate = test1.center;
ann2.name = @"test1";
[mapView addAnnotation:ann2];

MKCoordinateRegion test2 = { {0.0, 0.0} , {0.0, 0.0} }; //ändra ner
test2.center.latitude = 55.710113;
test2.center.longitude = 13.213500;
[mapView setRegion:test2 animated:YES];

testmap *ann3 = [[testmap alloc] init];
ann3.title = @"test2";
ann3.subtitle = @"Klicka här för mer info";
ann3.coordinate = test2.center;
ann3.name = @"test2";
[mapView addAnnotation:ann3];

MKCoordinateRegion test3 = { {0.0, 0.0} , {0.0, 0.0} };
test3.center.latitude = 55.708981;
test3.center.longitude = 13.197266;
[mapView setRegion:test3 animated:YES];

testmap *ann4 = [[testmap alloc] init];
ann4.title = @"test3";
ann4.subtitle = @"Klicka här för mer info";
ann4.coordinate = test3.center;
ann4.name = @"test3";
[mapView addAnnotation:ann4];

MKCoordinateRegion test4 = { {0.0, 0.0} , {0.0, 0.0} }; //ändra ner
test4.center.latitude = 55.705170;
test4.center.longitude = 13.191277;
[mapView setRegion:test4 animated:YES];

testmap *ann5 = [[testmap alloc] init];
ann5.title = @"test4";
ann5.subtitle = @"Klicka här för mer info";
ann5.coordinate = test4.center;
ann5.name = @"test4";
[mapView addAnnotation:ann5];
}

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

{

if ([annotation isKindOfClass:[MKUserLocation class]])
    return nil;
static NSString* AnnotationIdentifier = @"AnnotationIdentifier";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];




if(annotationView)
    return nil;
else
{
    MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation


  reuseIdentifier:AnnotationIdentifier];    annotationView.canShowCallout = YES;
   NSString* thisModelName = ((testmap*)annotation).name;

    if ([thisModelName isEqualToString:@"test1"]) {
    annotationView.image = [UIImage imageNamed:@"test1"];
    UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

        [rightButton setTitle:annotation.title forState:UIControlStateNormal];
        annotationView.rightCalloutAccessoryView = rightButton;
        annotationView.canShowCallout = YES;
        annotationView.draggable = YES;
        annotationView.highlighted = YES;

    return annotationView;
    }
    else if ([thisModelName isEqualToString:@"test2"])
    {
        annotationView.image = [UIImage imageNamed:@"test2"];
        UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        [rightButton addTarget:self action:@selector(myButton:) forControlEvents:UIControlEventTouchUpInside];
        [rightButton setTitle:annotation.title forState:UIControlStateNormal];
        annotationView.rightCalloutAccessoryView = rightButton;
        annotationView.canShowCallout = YES;
        annotationView.draggable = YES;
        annotationView.highlighted = YES;
        return annotationView;
    }
    else if ([thisModelName isEqualToString:@"test3"])
    {
        annotationView.image = [UIImage imageNamed:@"test3"];
        UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        [rightButton addTarget:self action:@selector(myButton:) forControlEvents:UIControlEventTouchUpInside];
        [rightButton setTitle:annotation.title forState:UIControlStateNormal];
        annotationView.rightCalloutAccessoryView = rightButton;
        annotationView.canShowCallout = YES;
        annotationView.draggable = YES;
        annotationView.highlighted = YES;
        return annotationView;
    }

     else if ([thisModelName isEqualToString:@"test4"])
    {
        annotationView.image = [UIImage imageNamed:@"test4"];
        UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        [rightButton addTarget:self action:@selector(myButton:) forControlEvents:UIControlEventTouchUpInside];
        [rightButton setTitle:annotation.title forState:UIControlStateNormal];
        annotationView.rightCalloutAccessoryView = rightButton;
        annotationView.canShowCallout = YES;
        annotationView.draggable = YES;
        annotationView.highlighted = YES;
        return annotationView;
    }
    }


     return nil;


     }

由于此代码,您将获得默认引脚 "randomly":

MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];

if (annotationView)
    return nil;

这段代码说的是如果 dequeueReusableAnnotationViewWithIdentifier: return 是一个视图(即如果 annotationView 而不是 nil ), return nil 来自委托方法。


当您从 viewForAnnotation 委托方法 return nil 时,地图视图将执行以下操作:

  • 如果注释类型为MKUserLocation,则显示默认的蓝点。
  • 如果注释不是 MKUserLocation,它将显示默认的红色图钉。

您可能的意思是:

MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];

if (annotationView)
    return annotationView;

但是,这会产生一个新问题,因为如果 dequeue return 是一个视图(a以前用于 不同 注释的视图),出队视图的 image 可能与当前 annotation 应该使用的图像不匹配。 =29=]

因此,当您缩放和平移地图时,注释图像会切换 "randomly"。

viewForAnnotation 中的正确方法是:

  1. 使用 dequeueReusableAnnotationViewWithIdentifier: 获取对视图的引用,如果 returns nil,则创建一个新视图。仅在创建新视图时设置对所有注释通用的视图属性。
  2. 使用在步骤 1 中获得的视图引用,设置特定于当前 annotation 的视图属性。如果正在使用出队视图,请同时更新其 annotation 属性。

示例:

- (MKAnnotationView *)mapView:(MKMapView *)mapview viewForAnnotation:(id <MKAnnotation>)annotation
{
    if (! [annotation isKindOfClass:[testmap class]])
    {
        //If annotation is NOT a "testmap" (eg. MKUserLocation),
        //return nil so map view displays default view for it...
        return nil;
    }

    static NSString* AnnotationIdentifier = @"AnnotationIdentifier";

    MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];

    if (! annotationView) {
        annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
        //set view properties common to all annotations...
        annotationView.canShowCallout = YES;
        UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        //Do not use addTarget with a custom method for callout accessories.
        //Instead, use the calloutAccessoryControlTapped delegate method shown below.
        annotationView.rightCalloutAccessoryView = rightButton;
        annotationView.draggable = YES;
    }
    else {
        //reusing a view, update its annotation to current...
        annotationView.annotation = annotation;
    }

    //AFTER we have a view reference, set annotation-specific properties...
    NSString* thisModelName = ((testmap*)annotation).name;

    if ([thisModelName isEqualToString:@"test1"]) {
        annotationView.image = [UIImage imageNamed:@"test1"];
    }
    else if ([thisModelName isEqualToString:@"test2"]) {
        annotationView.image = [UIImage imageNamed:@"test2"];
    }
    else if ([thisModelName isEqualToString:@"test3"]) {
        annotationView.image = [UIImage imageNamed:@"test3"];
    }
    else if ([thisModelName isEqualToString:@"test4"]) {
        annotationView.image = [UIImage imageNamed:@"test4"];
    }
    /*
     If image name will always be same as `name` property then
     can use single line instead of if/else statements:

         annotationView.image = [UIImage imageNamed:thisModelName];
     */

    return annotationView;
}

-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    if ([view.annotation isKindOfClass:[testmap class]]) {
        testmap *tm = (testmap *)view.annotation;
        NSLog(@"button for '%@' tapped", tm.name);
    }
}