ios - 将 UIImage 传递给 MKPinAnnotationView 时遇到问题

标签 ios objective-c uiimage parse-platform mkannotationview

我将 MKPointAnnotation 子类化并添加了一个 NSString 和一个 UIImage 这样我就可以将这些元素传递给 MKPinAnnotationView .字符串传递到 MKPinAnnotationView 正常,但图像属性作为 null 通过。我不知道为什么。我要说的是,有一次在我的手机上运行这段代码时,图像出现在一个 pin 上,所以也许我有内存泄漏?另外 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 是否有一个值,并且它是空的。我知道 NSLog 的这种用法并不优雅,但它应该返回图像的内存位置。它返回空值。同样,我的其他自定义属性 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 完成时,没有自动信号告诉注释 View 刷新其 leftCalloutAccessoryView

在这种情况下,粗略 解决方法是在选择注释时手动强制刷新 leftCalloutAccessoryView(即显示包含 leftCalloutAccessoryView).

当注释被选中时, map View 调用didSelectAnnotationView 委托(delegate)方法。在这里,可以应用粗略的解决方法:

-(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.restaurantIconnil,将左边的图标设置为一些通用的“加载”图标您添加到项目资源。在 didSelectAnnotationView 中,您还可以首先检查 fp.restaurantIcon 是否仍为 nil,如果是,则什么都不做(即,将图标保留为通用的“正在加载”图标)。

一个不太粗暴的解决方案可能是创建一个自定义注释 View 类,该类从其关联的注释中监听“图像已完成加载”消息并自动刷新。

关于ios - 将 UIImage 传递给 MKPinAnnotationView 时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20875278/

相关文章:

c++ - lib clang.dylib : change installation path

objective-c - 来自NSData的CGImageRef为空,但UIImage不是吗?

ios - 缩小UIImage

ios - 正确使用多个'If'语句?

iphone - 查询数据库 MySQL iOS 应用程序

ios - 如何访问 Objective-C 中的 Swift 扩展?

ios - 如何将文本转换为 UIImage(使用 GPU)

iOS 按钮动画,如邮件应用程序

ios - 从 NSMutableDictionary 获取所有值

ios - 如何在运行时在 Objective-C 中查找字符串常量?