MapKit注释视图标签出库时更改位置/在错误的注释中显示

问题描述

我要在地图图钉下方添加标签,以显示图钉的某些细节。我这样做是通过将UILabel添加为注释视图的子视图并将其行数设置为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;

解决方法

用于配置注释视图的所有代码都在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

结果是:

enter image description here

您可以根据自己的意愿显然地对其进行自定义,但希望它可以说明这一想法。

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

也许不用说,这里我使用的是注释的title属性,但是您可以检查注释子类并获取想要的任何属性,例如您的textToShow。但是,考虑到已经存在将文本字符串与注释相关联的属性,title(如果需要,可以选择subtitle),我会使用它。


您可能考虑将标签添加项移至PSMapAnnotationView的init方法中,因此注释视图将负责配置其子视图。而且,您可以覆盖annotation的{​​{1}}属性的设置方法,以为您设置标签文本。

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

viewDidLoad

然后您可以完全删除[self.mapView registerClass:[CustomAnnotationView class] forAnnotationViewWithReuseIdentifier:MKMapViewDefaultAnnotationViewReuseIdentifier]; (除非您需要支持多种注释类型)。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...