无法将UIImage传递给MKPinAnnotationView

我subclassed MKPointAnnotation并添加一个NSString和一个UIImage所以我可以将这些元素传递给一个MKPinAnnotationView 。 该string传递到MKPinAnnotationView罚款,但图像属性是通过为空。 我无法弄清楚为什么。 我会说有一次在我的手机上运行这个代码的图像出现在一个针一次,所以也许我有一个内存泄漏? 其他1000次我编译的图像在日志中显示为空,并没有出现。 任何帮助表示赞赏。

这是我的子类customMapAnnotation.h:

 @interface customMapAnnotation : MKPointAnnotation @property (strong, nonatomic) NSString *restaurantID; @property (strong, nonatomic) UIImage *restaurantIcon; @end 

这是我的customMapAnnotation创build的地方。 我正在使用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是否有一个值,它是空的。 我知道这个使用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的评论,因为图像被asynchronous加载到背景中,所以当viewForAnnotation被调用时,它们还没有加载,所以注解的标注卡住了一个空白的左侧图标。

当图像加载通过getDataInBackgroundWithBlock完成时,没有自动的信号告诉注解视图来刷新其leftCalloutAccessoryView视图。

在这种情况下,一个粗略的解决方法是手动强制刷新leftCalloutAccessoryView当注释被选中时(即显示包含leftCalloutAccessoryView的标注)。

选中注释后,地图视图将调用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; } } 

当然,图片仍然没有加载所select的注释(可能只是很长或图片url无效等)。

你可以做什么是在viewForAnnotation ,如果fp.restaurantIconnil ,左侧的图标设置为一个通用的“加载”图标,你添加到项目资源。 在didSelectAnnotationView ,您也可以先检查fp.restaurantIcon是否仍然nil ,如果是,则不做任何事情( fp.restaurantIcon图标保留为通用的“加载”图标)。

一个不太粗糙的解决scheme可能是创build一个自定义的注释视图类,它从相关注释中侦听“图像完成加载”消息并自动刷新。

我会说不要试图inheritanceMKPointAnnotation,创build自己的符合MKAnnotation协议的对象,并使用不是MKPinAnnotationViews的注解视图。