gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:38:40 27 4
gpt4 key购买 nike

我正在执行 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) initWithCoordinate:(CLLocationCoordinate2D) c;
- (CLLocationCoordinate2D) getCoordinate;
- (void) addPlace:(MapAnnotation*) 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)addPlace:(MapAnnotation *)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)initWithCoordinate:(CLLocationCoordinate2D) 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

map View :viewForAnnotation:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <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;
}

最佳答案

如评论中所述,除了 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 *)mapView:(MKMapView *)mapView viewForAnnotation:(id <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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com