• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

ios - 自定义注释在更新时不会在 map View 上更新

[复制链接]
菜鸟教程小白 发表于 2022-12-12 16:25:09 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我正在执行 willChangeValueForKeydidChangeValueForKey 调用,但即使使用它们,mapView 委托(delegate)也永远不会通过 mapView: viewForAnnotation: 来更新事情。如何强制更新 MKAnnotation

annotationView.image 不会在图像更改时更新,annotationView.image 也不会更新。据我的 NSLog 行所知,当 MKAnnotation 更新时,mapView: viewForAnnotation: 不会再次被调用。

.h

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface MapAnnotation : NSObject <MKAnnotation>

@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, retain) NSString *currentTitle;
@property (nonatomic, retain) NSString *currentSubTitle;
@property (nonatomic, retain) NSString *category;
@property (nonatomic, retain) NSString *pin;

- (NSString*) title;
- (NSString*) subtitle;
- (id) initWithCoordinateCLLocationCoordinate2D) c;
- (CLLocationCoordinate2D) getCoordinate;
- (void) addPlaceMapAnnotation*) place;
- (int) placesCount;
- (void) cleanPlaces;
- (UIImage *) getPin;
@end

.m

#import "MapAnnotation.h"

@interface MapAnnotation()
@property (strong) NSMutableArray *places;
@end

@implementation MapAnnotation

@synthesize coordinate      = _coordinate;
@synthesize currentTitle    = _currentTitle;
@synthesize currentSubTitle = _currentSubTitle;
@synthesize places          = _places;
@synthesize category        = _category;
@synthesize pin             = _pin;


- (NSString*) subtitle {
    if ([self placesCount] == 1) {
        return self.currentSubTitle;
    }
    else{
        return @"";
    }
}


- (NSString*) title {
    if ([self placesCount] == 1) {
        return self.currentTitle;
    }
    else{
        return [NSString stringWithFormat"%d places", [self placesCount]];
    }
}


- (void)addPlaceMapAnnotation *)place {
    [self willChangeValueForKey"title"];
    [self willChangeValueForKey"subtitle"];
    [self.places addObject:place];
    [self didChangeValueForKey"title"];
    [self didChangeValueForKey"subtitle"];
}


- (CLLocationCoordinate2D)getCoordinate {
    return self.coordinate;
}


- (void)cleanPlaces {
    [self willChangeValueForKey"title"];
    [self willChangeValueForKey"subtitle"];
    [self.places removeAllObjects];
    [self.places addObject:self];
    [self didChangeValueForKey"title"];
    [self didChangeValueForKey"subtitle"];
}


- (id)initWithCoordinateCLLocationCoordinate2D) c {
    self.coordinate=c;
    self.places=[[NSMutableArray alloc] initWithCapacity:0];
    return self;
}


- (int)placesCount {
    return [self.places count];
}


- (UIImage *)getPin {
    // begin a graphics context of sufficient size
    CGSize size = CGSizeMake(26, 26);
    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);

    // get the context for CoreGraphics
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGRect imageRect = CGRectMake(0, 0, size.width, size.height);

    // Draw Dot
    CGRect circleRect = CGRectInset(imageRect, 4, 4);
    [[UIColor blackColor] setStroke];
    [[UIColor yellowColor] setFill];
    CGContextFillEllipseInRect(ctx, circleRect);
    CGContextStrokeEllipseInRect(ctx, circleRect);

    // Dot Content
    [[UIColor blackColor] setStroke];
    [[UIColor blackColor] setFill];
    CGAffineTransform transform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
    CGContextSetTextMatrix(ctx, transform);
    CGContextSetLineWidth(ctx, 2.0);
    CGContextSetCharacterSpacing(ctx, 1.7);
    CGContextSetTextDrawingMode(ctx, kCGTextFill);
    UIFont *font = [UIFont fontWithName"Arial" size:11.0];
    if ([self placesCount] != 1) {
        NSString *label = [NSString stringWithFormat:@"%d", [self placesCount]];
        CGSize stringSize = [label sizeWithAttributes:@{NSFontAttributeName:font}];
        [label drawAtPoint:CGPointMake(size.width / 2 - stringSize.width / 2, size.height / 2 - stringSize.height / 2)
            withAttributes:@{NSFontAttributeName:font}];
    } else {
        NSString *label = [NSString stringWithFormat:@"%@", self.pin];
        CGSize stringSize = [label sizeWithAttributes:@{NSFontAttributeName:font}];
        [label drawAtPoint:CGPointMake(size.width / 2 - stringSize.width / 2, size.height / 2 - stringSize.height / 2)
            withAttributes:@{NSFontAttributeName:font}];
    }


    // make image out of bitmap context
    UIImage *retImage = UIGraphicsGetImageFromCurrentImageContext();

    // free the context
    UIGraphicsEndImageContext();

    return retImage;
}

@end

ma​​pView:viewForAnnotation:

- (MKAnnotationView *)mapViewMKMapView *)mapView viewForAnnotationid <MKAnnotation>)annotation {
    MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"MyAnnoation"];
    if(!annotationView) {
        annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"MyAnnoation"];
        annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    }

    annotationView.enabled = YES;
    if ([(MapAnnotation*)annotation placesCount] == 1) {
        annotationView.canShowCallout = YES;
    }
    annotationView.image = [(MapAnnotation*)annotation getPin];
    NSLog(@"%@", [annotation title]);

    return annotationView;
}



Best Answer-推荐答案


正如评论中提到的,除了 titlesubtitle 之外,注释属性的更改不会自动导致 View 更新。

更改 titlesubtitle 将在显示时自动更新标注,只要更改导致 KVO 通知(例如,如果使用带有 ann.title = xxx 或通过手动发出 KVO 通知,因为您有自定义 getter)。

要自动更新图像,您可能需要使用自定义注释 View 来观察底层注释属性的变化并自行刷新(在 init 中调用 addObserver ,在observeValueForKeyPath更新图片,在dealloc调用removeObserver)。您也可以使用非 KVO 方法,例如自定义通知或委托(delegate)(但仍使用自定义注释 View )来实现。

使用现有代码,在不创建自定义注释 View 和使用KVO等的情况下,快速手动更新注释 View 的方法是在注释更新后立即获取注释的当前 View 并更新图像 属性。只要 viewForAnnotation 中的代码与设置 image 的逻辑相同,这应该可以工作。

我假设在应用程序的某个地方(有时注释已经添加),它通过调用addPlace来更新注释中的位置。之后,您可以尝试以下操作:

[someExistingAnnotation addPlace:anotherPlace];

//obtain the current view of someExistingAnnotation...
MKAnnotationView *av = [mapView viewForAnnotation:someExistingAnnotation];

//update its image property to force refresh...
av.image = [someExistingAnnotation getPin];
//also set canShowCallout (it might have been NO)


不相关但当前的 viewForAnnotation 不能正确处理可能的 View 重用和/或除您的自定义注释之外的注释类型(例如会导致当前代码崩溃的用户位置蓝点)。我建议将其更改为:

- (MKAnnotationView *)mapViewMKMapView *)mapView viewForAnnotationid <MKAnnotation>)annotation {
    if (! [annotation isKindOfClass:[MapAnnotation class]])
    {
        //annotation is NOT a "MapAnnotation", return nil for default view...
        return nil;
    }

    MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"MyAnnoation"];
    if(!annotationView) {
        annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"MyAnnoation"];
        annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    }

    //update view's annotation to current in case it's being re-used
    annotationView.annotation = annotation;

    annotationView.enabled = YES;
    if ([(MapAnnotation*)annotation placesCount] == 1) {
        annotationView.canShowCallout = YES;
    }
    else {
        annotationView.canShowCallout = NO;
    }

    annotationView.image = [(MapAnnotation*)annotation getPin];
    NSLog(@"%@", [annotation title]);

    return annotationView;
}

关于ios - 自定义注释在更新时不会在 map View 上更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20026321/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap