Ios MKAnnotation setImage适用于iPhone,但不适用于iPad/iPhone 6+;

Ios MKAnnotation setImage适用于iPhone,但不适用于iPad/iPhone 6+;,ios,ipad,mkmapview,mkannotation,mkannotationview,Ios,Ipad,Mkmapview,Mkannotation,Mkannotationview,我正在尝试为MKMapView中的MKPointAnnotation设置自定义图像。除6+外,所有iPhone上的图像设置均正确: 但在iPhone 6+和iPad上,注释有默认pin而不是我的图片: 下面是设置注释图像的代码,以及Images.xcsets中parking_spot_icon.png的条目。我的任何代码都不依赖于设备的大小,并且没有相关的错误或生成警告(特别是,没有关于错误图像大小的警告) 我尝试过单步执行代码,我看到UIImage*图像在这两种情况下(iPhone和iPa

我正在尝试为MKMapView中的MKPointAnnotation设置自定义图像。除6+外,所有iPhone上的图像设置均正确:

但在iPhone 6+和iPad上,注释有默认pin而不是我的图片:

下面是设置注释图像的代码,以及Images.xcsets中parking_spot_icon.png的条目。我的任何代码都不依赖于设备的大小,并且没有相关的错误或生成警告(特别是,没有关于错误图像大小的警告)

我尝试过单步执行代码,我看到UIImage*图像在这两种情况下(iPhone和iPad)都作为以下对象打印:

这是我的停车场图标图像资源:


我能看到的唯一区别是iPad使用了不同的图像比例;但我包括了所有刻度的图标。我觉得我错过了一些明显的东西。有人能想出为什么我的图像可以在iPhone上设置而不是在iPad/6+上设置的原因吗?

要为注释视图设置自定义图像,必须实现
viewForAnnotation
委托方法

您不能调用地图视图的
viewForAnnotation
实例方法并在该视图上设置
image
,因为这将是一次性执行,不会“粘住”视图

当地图视图稍后需要此注释或其他注释的视图时(这可能在添加注释后很长时间),它将调用委托方法(如果实现)。如果未实现委托方法,则地图视图将为您显示默认的红色pin

与iPad相比,它在iPhone上“工作”只是随机的、不可预测的行为,你不应该依赖它

viewForAnnotation
delegate方法的示例实现:

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        //if this is the user location, return nil so map view
        //draws default blue dot for it...
        return nil;
    }

    static NSString *reuseId = @"ann";

    MKAnnotationView *av = [mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
    if (av == nil) {
        av = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId];
        av.canShowCallout = YES;
        UIImage *image = [UIImage imageNamed:@"parking_spot_icon.png"];
        av.image = image;
    }
    else {
        //we are recycling a view previously used for another annotation,
        //update its annotation reference to the current one...
        av.annotation = annotation;
    }

    return av;
}
-(MKAnnotationView*)地图视图:(MKMapView*)地图视图注释:(id)注释
{
if([annotation isKindOfClass:[MKUserLocation类]]){
//如果这是用户位置,则返回nil so map view
//为它绘制默认的蓝点。。。
返回零;
}
静态NSString*reuseId=@“ann”;
MKAnnotationView*av=[mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
如果(av==nil){
av=[[MKAnnotationView alloc]initWithAnnotation:annotation-reuseIdentifier:reuseId];
av.canShowCallout=是;
UIImage*image=[UIImage ImageName:@“parking_spot_icon.png”];
av.image=图像;
}
否则{
//我们正在回收以前用于另一个注释的视图,
//将其注释引用更新为当前注释引用。。。
av.annotation=注释;
}
返回av;
}
确保地图视图的
delegate
属性已设置,或者其出口已连接到情节提要/xib中的视图控制器,否则即使已实现delegate方法,也不会调用该方法



在创建批注时,您还应该删除对
selectAnnotation
deselectAnnotation
的调用--它们不是必需的。

您添加了@3x图像吗?感谢Ashish,我在我的资源中添加了所有3个缩放图像。您是否已经实现了
viewForAnnotation
delegate方法,并且正在那里创建MKAnnotationView?直接调用viewForAnnotation并按照问题中的代码设置图像不是这样做的。谢谢Anna,将我的设置图像放在viewForAnnotation中很有效!现在我在所有设备上都有了自定义注释。非常感谢更新,它也回答了我的下一个问题,即“如何更改除用户位置以外的所有注释?”嗨,我收到了相同的问题,它适用于视网膜设备上的(@2x)图像,但对于6+我需要(@3x)图像,而对于6+则不适用。有什么帮助吗?如果你知道这样的问题,请检查一下。
(lldb) p *image
(UIImage) $0 = {
  NSObject = {
    isa = UIImage
  }
   _imageRef = 0x00007fd2d733fd30 // differs run-to-run
  _scale = 3 // 2 on iPhone, 3 on iPad
  _imageFlags = {
    named = 1
    imageOrientation = 0
    cached = 0
    hasPattern = 0
    isCIImage = 0
    renderingMode = 0
    suppressesAccessibilityHairlineThickening = 0
    hasDecompressionInfo = 0
  }
}
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        //if this is the user location, return nil so map view
        //draws default blue dot for it...
        return nil;
    }

    static NSString *reuseId = @"ann";

    MKAnnotationView *av = [mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
    if (av == nil) {
        av = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId];
        av.canShowCallout = YES;
        UIImage *image = [UIImage imageNamed:@"parking_spot_icon.png"];
        av.image = image;
    }
    else {
        //we are recycling a view previously used for another annotation,
        //update its annotation reference to the current one...
        av.annotation = annotation;
    }

    return av;
}