【问题标题】:Having trouble passing UIImage to MKPinAnnotationView将 UIImage 传递给 MKPinAnnotationView 时遇到问题
【发布时间】:2014-01-02 01:56:23
【问题描述】:

我将MKPointAnnotation 子类化并添加了NSStringUIImage,因此我可以将这些元素传递给MKPinAnnotationView。该字符串传入MKPinAnnotationView 罚款,但图像属性作为空值传入。我不知道为什么。我会说有一次在我的手机上运行此代码时,图像出现在针上一次,所以也许我有内存泄漏?我编译的其他 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;
    }
}

【问题讨论】:

  • 我认为这可能是由您的背景图像加载器 getDataInBackgroundWithBlock 引起的。您可以在 UIImageView *profileIconView 中设置断点并检查 fp.restaurantIcon 是否为 nil。可能在您创建 MKPinAnnotationView 时,restaurantIcon 仍为 nil。
  • 你可以试试这个,UIImageView *profileIconView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 37, 31)]; profileIconView.clipsToBounds = YES; profileIconView.image = fp.restaurantIcon; pinView.leftCalloutAccessoryView = profileIconView;

标签: ios objective-c uiimage parse-platform mkannotationview


【解决方案1】:

我同意@Vincent 的评论,即由于图像是在后台异步加载的,所以在调用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;
    }
}

当然,可能仍然没有为所选注释加载图像(它只是花费了很长时间或图像网址无效等)。

您可以在viewForAnnotation 中做,如果fp.restaurantIconnil,则将左侧图标设置为您添加到项目资源中的一些通用“加载”图标。在didSelectAnnotationView 中,您还可以先检查fp.restaurantIcon 是否仍为nil,如果是,则不执行任何操作(即,将图标保留为通用的“加载”图标)。

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

【讨论】:

  • 我尝试了 didSelectAnnotationView 方法,但它没有改变任何东西。我认为我在图像加载时间或 url 方面没有任何问题,因为我的 tableViewControllers 显示相同对象的图像没有问题。我在上面的问题中添加了该方法的代码。
  • 您是否将委托方法命名为mainMap:didSelectAnnotationView:?将其命名为 mainMap: 将不起作用,因为地图视图专门寻找 mapView:didSelectAnnotationView:。使用委托方法,您可以更改内部参数名称,但不能更改可见的方法签名。
  • 我在那里打字太快了;你是完全正确的。我在委托方法中错误地输入了我的地图对象名称。很惊讶它没有踢出错误。 didSelectAnnotation 修复了问题并迅速加载图像。
【解决方案2】:

我想说不要尝试继承 MKPointAnnotation,创建符合 MKAnnotation 协议的您自己的对象,并使用不是 MKPinAnnotationViews 的注释视图。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多