我将MKPointAnnotation
子类化,并添加了NSString
和UIImage
,以便可以将这些元素传递给MKPinAnnotationView
。该字符串很好地传递到MKPinAnnotationView
中,但是image属性作为null传递。我不知道为什么。我会说,一次在手机上运行此代码,图像一次出现在大头针上,所以也许我内存泄漏了?我编译图像的其他1000次在日志中显示为null,并且不显示。任何帮助表示赞赏。
这是我的子类customMapAnnotation.h:
@interface customMapAnnotation : MKPointAnnotation
@property (strong, nonatomic) NSString *restaurantID;
@property (strong, nonatomic) UIImage *restaurantIcon;
@end
这是创建我的
customMapAnnotation
的地方。我正在使用Parse.com,所以这里有一条语句可以将PFFile转换为UIImage。如果检查日志,则在运行时确认foodPoint.restaurantIcon
具有值。customMapAnnotation *foodPoint = [[customMapAnnotation alloc] init];
foodPoint.coordinate = spot;
foodPoint.restaurantID = [object objectId];
foodPoint.title = [object objectForKey:@"restaurantName"];
foodPoint.subtitle = [object objectForKey:@"cuisineType"];
leftIcon = [object objectForKey:@"restaurantImage"];
[leftIcon getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
image = [UIImage imageWithData:data];
// image can now be set on a UIImageView
foodPoint.restaurantIcon = image;
}
}];
[self.mainMap addAnnotation:foodPoint];
现在这是我的
MKPinAnnotationView
的所有代码。请注意,我运行NSLog
来确认fp.restaurantIcon
是否具有值,并且它为null。我知道NSLog
的这种用法不太合适,但是它应该返回图像的内存位置。它返回null。同样,我的其他自定义属性fp.restaurantId
运行正常。- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
static NSString *identifier = @"RoutePinAnnotation";
if (annotation == mapView.userLocation)
{
return nil;
}
else
{
MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:identifier];
pinView.animatesDrop=NO;
pinView.canShowCallout=YES;
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
//cast annotation parameter to our class so compiler understands...
customMapAnnotation *fp = (customMapAnnotation *)annotation;
NSLog(fp.restaurantIcon);
//get restaurantID from the annotation parameter ("fp")...
[rightButton setTitle:fp.restaurantID forState:UIControlStateNormal];
[rightButton addTarget:self
action:@selector(buttonMethod:)
forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = rightButton;
//NSLog(fp.restaurantIcon);
UIImageView *profileIconView = [[UIImageView alloc] initWithImage:fp.restaurantIcon];
profileIconView.frame = CGRectMake(0,0,31,31);
pinView.leftCalloutAccessoryView = profileIconView;
return pinView;
}
}
这是我的
didSelectAnnotationView:
- (void) mainMap:(MKMapView *)mainMap didSelectAnnotationView:(MKAnnotationView *)view
{
if ([view.annotation isKindOfClass:[chwMapAnnotation class]])
{
chwMapAnnotation *fp = (chwMapAnnotation *)view.annotation;
UIImageView *profileIconView = [[UIImageView alloc] initWithImage:fp.restaurantIcon];
profileIconView.frame = CGRectMake(0,0,31,31);
view.leftCalloutAccessoryView = profileIconView;
}
}
最佳答案
我同意@Vincent的评论,因为图像是异步加载到后台的,所以在调用viewForAnnotation
时还没有加载图像,因此注释的标注被留有空白的左图标。
通过getDataInBackgroundWithBlock
完成图像加载后,没有自动信号告诉注释视图刷新其leftCalloutAccessoryView
。
在这种情况下,一种粗略的解决方法是在选择注释时(即在显示包含leftCalloutAccessoryView
的标注时)手动强制刷新leftCalloutAccessoryView
。
选择注释后, map 视图将调用didSelectAnnotationView
委托方法。在这里,可以应用粗略的解决方法:
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
if ([view.annotation isKindOfClass:[customMapAnnotation class]])
{
customMapAnnotation *fp = (customMapAnnotation *)view.annotation;
UIImageView *profileIconView = [[UIImageView alloc] initWithImage:fp.restaurantIcon];
profileIconView.frame = CGRectMake(0,0,31,31);
view.leftCalloutAccessoryView = profileIconView;
}
}
当然,可能还没有为所选的注释加载图像(可能只是花费了很长时间,或者图像的URL无效,等等)。
您可以在
viewForAnnotation
中进行操作,如果fp.restaurantIcon
是nil
,则将左侧图标设置为添加到项目资源中的某个通用“正在加载”图标。在didSelectAnnotationView
中,您还可以首先检查fp.restaurantIcon
是否仍为nil
,如果是,则什么也不做(即,将图标保留为通用的“正在加载”图标)。不太简单的解决方案是创建一个自定义注释视图类,该类从其关联的注释中侦听“图像已完成加载”消息,并自动刷新自身。