iPhone MapKit 问题:viewForAnnotation 设置 pinColor 不一致?

发布于 2024-09-05 05:23:51 字数 2236 浏览 4 评论 0原文

我正在尝试设置一个地图,根据相关位置的类型/类别显示不同的图钉颜色。我知道这是一件很常见的事情,但我无法让 viewForAnnotation 委托持续更新/设置图钉颜色。
我有一个 showThisLocation 函数,它基本上循环遍历 AddressAnnotations 列表,然后根据注释类(公交车站、医院等)设置一个


if( myClass == 1){
 [defaults setObject:@"1" forKey:@"currPinColor"];
 [defaults synchronize];
 NSLog(@"Should be %@!", [defaults objectForKey:@"currPinColor"]);
} else if( myClass ==2 ){
 [defaults setObject:@"2" forKey:@"currPinColor"];
 [defaults synchronize];
 NSLog(@"Should be %@!", [defaults objectForKey:@"currPinColor"]);
}
[_mapView addAnnotation:myCurrentAnnotation];

然后我的 viewForAnnotation 委托看起来像这样,


- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
    if( annotation == mapView.userLocation ){ return nil; }

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    MKPinAnnotationView *annView = nil;
    annView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"currentloc"];
    if( annView == nil ){
        annView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"currentloc"];
    }

    annView.pinColor =  [defaults integerForKey:@"currPinColor"];
    NSLog(@"Pin color: %d", [defaults integerForKey:@"currPinColor"]);
    annView.animatesDrop=TRUE;
    annView.canShowCallout = YES;
    annView.calloutOffset = CGPointMake(-5, 5);
    return annView;
}

问题是,尽管 NSLog 语句“if”块始终确认颜色已设置,委托有时但并不总是以正确的颜色结束。我还注意到,通常发生的情况是,第一次搜索新位置会将所有引脚设置为“if”块中的最后一种颜色,但再次搜索相同位置会将引脚设置为正确的颜色。

我怀疑我不应该以这种方式使用 NSUserDefaults,但我也尝试为 MKAnnotation 创建自己的子类,其中包括一个附加属性“currentPinColor”,虽然这允许我设置“currentPinColor”,但当我尝试访问时来自委托方法的“currentPinColor”,编译器抱怨它不知道与 MKAnnotation 相关的“currentPinColor”。我想这很公平,但后来我尝试修改委托方法,


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

而不是默认方法,


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

此时编译器抱怨它对此委托上下文中的 MyCustomMKAnnotation 协议一无所知。

设置委托方法和/或 MyCustomMKAnnotation 的正确方法是什么,或者实现一致的 pinColor 设置的正确方法是什么。我几乎没有什么想法可以在这里尝试。

I'm trying setup a map that displays different pin colors depending on the type/class of the location in question. I know this is a pretty common thing to do, but I'm having trouble getting the viewForAnnotation delegate to consistently update/set the pin color.
I have a showThisLocation function that basically cycles through a list of AddressAnnotations and then based on the annotation class (bus stop, hospital, etc.) I set an


if( myClass == 1){
 [defaults setObject:@"1" forKey:@"currPinColor"];
 [defaults synchronize];
 NSLog(@"Should be %@!", [defaults objectForKey:@"currPinColor"]);
} else if( myClass ==2 ){
 [defaults setObject:@"2" forKey:@"currPinColor"];
 [defaults synchronize];
 NSLog(@"Should be %@!", [defaults objectForKey:@"currPinColor"]);
}
[_mapView addAnnotation:myCurrentAnnotation];

then my viewForAnnotation delegate looks like this,


- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
    if( annotation == mapView.userLocation ){ return nil; }

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    MKPinAnnotationView *annView = nil;
    annView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"currentloc"];
    if( annView == nil ){
        annView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"currentloc"];
    }

    annView.pinColor =  [defaults integerForKey:@"currPinColor"];
    NSLog(@"Pin color: %d", [defaults integerForKey:@"currPinColor"]);
    annView.animatesDrop=TRUE;
    annView.canShowCallout = YES;
    annView.calloutOffset = CGPointMake(-5, 5);
    return annView;
}

The problem is that, although the NSLog statements in the "if" block always confirm that the color has been set, the delegate sometimes but not always ends up with the correct color. I've also noticed that what generally happens is that the first search for a new location will set all pins to the last color in the "if" block, but search for the same location again will set the pins to the correct color.

I suspect I am not supposed to usen NSUserDefaults in this way, but I also tried to create my own subclass for MKAnnotation which included an additional property "currentPinColor", and while this allowed me to set the "currentPinColor", when I tried to access the "currentPinColor from the delegate method, the compiler complained that it didn't know anything about "currentPinColor in connection with MKAnnotation. Fair enough I guess, but then I tried to revise the delegate method,


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

instead of the default


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

at which point the compiler complained that it didn't know anything about the protocol for MyCustomMKAnnotation in this delegate context.

What is the proper way to set the delegate method and/or MyCustomMKAnnotation, or what is the appropriate way to achieve consistent pinColor settings. I'm just about out of ideas for things to try here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无声静候 2024-09-12 05:23:51

我解决了我自己的问题。有时只需提出问题就足够了!
问题是我尝试访问 MKAnnotation 委托的方式。

发帖后,我碰巧看到了这两篇相关的帖子,

MKPinAnnotationView:是否有超过三种颜色可用?

Mapkit 在查找注释当前位置时出现问题

用户 Cannonade 对第一篇文章的回答表明,


- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{   
    // ... get the annotation delegate and allocate the MKAnnotationView (annView)
    if ([annotationDelegate.type localizedCaseInsensitiveCompare:@"NeedsBluePin"] == NSOrderedSame)
    {
        UIImage * image = [UIImage imageNamed:@"blue_pin.png"];
        UIImageView *imageView = [[[UIImageView alloc] initWithImage:image] autorelease];
        [annView addSubview:imageView];
    }
    // ...

但是我的问题是我不知道如何获取委托,并且它漂浮在上面代码片段的 ... 省略号部分的某个地方。第二篇文章的答案,也是由用户 Cannonade 填写的,填补了这个缺失的部分,


- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    AnnotationDelegate * delegate = (AnnotationDelegate*)view.annotation;
    // do stuff with delegate.position;
}

将这两个片段放在一起产生了期望的结果,并最终解决了我的问题。

工作的 viewForAnnotation 委托方法看起来像这样,


- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
    if( annotation == mapView.userLocation ){ return nil; }
    AddressAnnotation *delegate = annotation;  //THIS CAST WAS WHAT WAS MISSING!
    MKPinAnnotationView *annView = nil;
    annView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"currentloc"];
    if( annView == nil ){
        annView = [[MKPinAnnotationView alloc] initWithAnnotation:delegate reuseIdentifier:@"currentloc"];
    }

    if ([delegate.classPinColor localizedCaseInsensitiveCompare:@"green"] == NSOrderedSame) {
        annView.pinColor = MKPinAnnotationColorGreen;
    }else if ([delegate.classPinColor localizedCaseInsensitiveCompare:@"purple"] == NSOrderedSame){
        annView.pinColor = MKPinAnnotationColorPurple;
    }else if ([delegate.classPinColor localizedCaseInsensitiveCompare:@"red"] == NSOrderedSame){
        annView.pinColor = MKPinAnnotationColorRed;
    }
    annView.animatesDrop=TRUE;
    annView.canShowCallout = YES;
    annView.calloutOffset = CGPointMake(-5, 5);
    return annView;
}

希望这对其他人有帮助。

谢谢加农炮!

I solved my own problem. Sometimes just formulating the question is enough!
The issue was the way I was trying to access my MKAnnotation delegate.

After posting I happened on these two related posts,

MKPinAnnotationView: Are there more than three colors available?

Mapkit issue in finding annotation current position

The answer to the first post, by user Cannonade, suggests


- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{   
    // ... get the annotation delegate and allocate the MKAnnotationView (annView)
    if ([annotationDelegate.type localizedCaseInsensitiveCompare:@"NeedsBluePin"] == NSOrderedSame)
    {
        UIImage * image = [UIImage imageNamed:@"blue_pin.png"];
        UIImageView *imageView = [[[UIImageView alloc] initWithImage:image] autorelease];
        [annView addSubview:imageView];
    }
    // ...

however my issue was that I didn't know how to the get the delegate and it was floating around somewhere in the ... ellipsis part of the above snippet. The answer to the second post, also by user Cannonade, filled this missing bit in,


- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    AnnotationDelegate * delegate = (AnnotationDelegate*)view.annotation;
    // do stuff with delegate.position;
}

Putting these two snippets together produced the desired result and finally solved my problem.

The working viewForAnnotation delegate method then looks like,


- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
    if( annotation == mapView.userLocation ){ return nil; }
    AddressAnnotation *delegate = annotation;  //THIS CAST WAS WHAT WAS MISSING!
    MKPinAnnotationView *annView = nil;
    annView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"currentloc"];
    if( annView == nil ){
        annView = [[MKPinAnnotationView alloc] initWithAnnotation:delegate reuseIdentifier:@"currentloc"];
    }

    if ([delegate.classPinColor localizedCaseInsensitiveCompare:@"green"] == NSOrderedSame) {
        annView.pinColor = MKPinAnnotationColorGreen;
    }else if ([delegate.classPinColor localizedCaseInsensitiveCompare:@"purple"] == NSOrderedSame){
        annView.pinColor = MKPinAnnotationColorPurple;
    }else if ([delegate.classPinColor localizedCaseInsensitiveCompare:@"red"] == NSOrderedSame){
        annView.pinColor = MKPinAnnotationColorRed;
    }
    annView.animatesDrop=TRUE;
    annView.canShowCallout = YES;
    annView.calloutOffset = CGPointMake(-5, 5);
    return annView;
}

Hopefully this will be of help to someone else.

Thanks Cannonade!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文