【问题标题】:MapKit annotation view labels changing position/showing in wrong annotation when dequeuedMapKit 注释视图标签在出列时更改位置/显示错误注释
【发布时间】:2021-02-11 00:56:21
【问题描述】:

我在地图图钉下方添加标签以显示图钉的一些细节。我这样做是通过添加 UILabel 作为 annotationView 的子视图并将其行数设置为 0 以便在同一标签上显示多行。我遇到了一个问题,地图最初加载了正确的注释,我可以在地图图钉的标签中看到正确的数据,但是当我导航到另一个屏幕然后返回地图时,地图图钉是都在正确的位置,但它们下面的标签不再在标签中显示正确的数据,它们都被混淆了。地图图钉开始显示属于其他地图图钉的数据。此外,如果我将地图移动一点,然后回到同一个引脚,也会发生同样的事情。

我在 viewForAnnotation 方法中给标签添加数据:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
// Return the view marker different for editing items ie draggable undragrable.

    if ([annotation isKindOfClass:[PSMapAnnotation class]] == YES) {
        PSMapAnnotation *senderAnnotation = (PSMapAnnotation *)annotation;
        PSMapAnnotationView *annotationView = (PSMapAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:[senderAnnotation getPinKey]];

        if (annotationView == nil) {
            annotationView = [[PSMapAnnotationView alloc]
                              initWithAnnotation:senderAnnotation
                              reuseIdentifier:[senderAnnotation getPinKey]];
            



            // THIS LINE RETURNS A STRING ARRAY CONTAINING LABEL DATA

            NSMutableArray *taggedAnswers = [self _getTaggedAnswersForMarkerLabel:annotationView];
            

            annotationView.enabled = YES;
            annotationView.canShowCallout = NO;
            
            UILabel *annotationLabel = [[UILabel alloc] init];
            
            annotationLabel.text = @"";
            annotationLabel.numberOfLines = 0;
            annotationLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:14.0];
            annotationLabel.textColor = [UIColor blackColor];
            annotationLabel.textAlignment = NSTextAlignmentCenter;

            // LOOP THROUGH STRING ARRAY AND ADD ALL STRINGS TO ANNOTATION LABEL
            
            for (NSString* taggedAnswer in taggedAnswers)
            {
                
                NSString *textToShow = [NSString stringWithFormat: @"%@\n", taggedAnswer];

                annotationLabel.text = [annotationLabel.text stringByAppendingString: textToShow];

            }
            
            [annotationLabel sizeToFit];
            annotationLabel.center = CGPointMake(annotationView.center.x, annotationView.center.y);
            
            
            annotationView.myLabel = annotationLabel;
            [annotationView addSubview:annotationLabel];
            
            
            [annotationView setAnnotation:annotation];
            

        }
        else {
            
            [annotationView setAnnotation:annotation];
            
        }
        return annotationView;

【问题讨论】:

    标签: ios objective-c mapkit mapkitannotation


    【解决方案1】:

    用于配置注释视图的所有代码都在 if (annotationView == nil) { ... } 块内。所以,如果它成功地重用了一个注解视图(你的 else 块),你就没有设置标签。

    您应该将annotationLabel.text = ... 代码移到此if 语句之外。例如

    if (annotationView == nil) {
         // instantiate annotation view and add subview, but don’t set the `text` of the label yet
    } else {
         annotationView.annotation = annotation;
    }
    
    annotationView.annotationLabel.text = ...
    

    例如

    //  CustomAnnotationView.h
    
    @import UIKit;
    @import MapKit;
    
    @interface CustomAnnotationView : MKPinAnnotationView
    @end
    

    //  CustomAnnotationView.m
    
    #import "CustomAnnotationView.h"
    
    @interface CustomAnnotationView ()
    @property (nonatomic) UILabel *label;
    @end
    
    @implementation CustomAnnotationView
    
    - (instancetype)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
        self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
        if (self) {
            self.enabled = YES;
            self.canShowCallout = NO;
    
            self.label = [[UILabel alloc] init];
            self.label.translatesAutoresizingMaskIntoConstraints = false;
            self.label.text = @"";
            self.label.numberOfLines = 0;
            self.label.font = [UIFont fontWithName:@"HelveticaNeue" size:14.0];
            self.label.textColor = [UIColor labelColor];
            self.label.textAlignment = NSTextAlignmentCenter;
            [self addSubview:self.label];
    
            [NSLayoutConstraint activateConstraints:@[
                [self.label.topAnchor constraintEqualToAnchor:self.bottomAnchor constant:8],
                [self.label.centerXAnchor constraintEqualToAnchor:self.centerXAnchor constant:-self.centerOffset.x]
            ]];
    
            [self updateForAnnotation:annotation];
        }
    
        return self;
    }
    
    - (void)setAnnotation:(id<MKAnnotation>)annotation {
        [super setAnnotation:annotation];
        [self updateForAnnotation:annotation];
    }
    
    - (void)updateForAnnotation:(id<MKAnnotation>)annotation {
        self.label.text = annotation.title;
    }
    
    @end
    

    产生:

    根据您的需要清楚地自定义它,但希望它能说明这个想法。

    注意使用约束来确保标签始终居中。

    可能不用说,这里我使用注解的title 属性,但是您可以检查您的注解子类并获取您想要的任何属性,例如你的textToShow。但是鉴于已经有一个属性可以将文本字符串与注释关联起来,要么是title(如果需要,还可以选择subtitle),我会使用它。


    您可能会考虑将标签的添加移动到PSMapAnnotationView init 方法中,以便注释视图负责配置其子视图。并且您可以覆盖PSMapAnnotationViewannotation 属性的设置器来为您设置标签文本。

    这样做的好处是 (a) 它简化了您的 MKMapViewDelegate 代码; (b) 将子视图配置保留在其所属的位置; (c) 如果仅支持 iOS 11 及更高版本,则为彻底消除 viewForAnnotation 打开大门。例如。在viewDidLoad 中添加一行内容:

    [self.mapView registerClass:[CustomAnnotationView class] forAnnotationViewWithReuseIdentifier:MKMapViewDefaultAnnotationViewReuseIdentifier];
    

    然后您可以完全删除viewForAnnotation(除非您需要支持多种注释类型)。

    【讨论】:

    • 我尝试按照您的建议(在返回 annotationView 之前)在 if 语句之外设置标签的文本,但现在标签上根本没有显示任何文本。
    • 您的框架可能没有重置。就个人而言,我会将translatesAutoresizingMaskIntoConstraints 设置为false 并使用约束,如我的示例所示。
    • 非常感谢你,这是一个巨大的帮助,是一个非常有用的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 2011-02-15
    • 2011-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多