从子目录加载视网膜图像

Posted

技术标签:

【中文标题】从子目录加载视网膜图像【英文标题】:Loading retina images from a subdirectory 【发布时间】:2013-05-10 05:14:50 【问题描述】:

我正在使用NSDrawNinePartImage() 来绘制可拉伸控件。因为这当然需要九个单独的图像来绘制零件(加上一些在上面绘制的额外内容),所以我有一个充满文件的目录,例如top-left.pngtop-left@2x.png。我将此目录作为文件夹引用包含在我的应用程序包中。

不幸的是,-[NSImage imageNamed:]-[NSBundle imageForResource:] 等常用的图像加载 API 似乎不支持子目录,即使您在名称中添加了斜线也是如此。相反,我使用这种方法加载图像:

- (NSImage*)popoverImage:(NSString*)name 
    NSURL * url = [[NSBundle bundleForClass:self.class] URLForResource:name withExtension:@"png" subdirectory:@"popover"];
    return [[NSImage alloc] initWithContentsOfURL:url];

这适用于普通显示器,但它忽略了视网膜显示器的 2x 图像。我怎样才能让它也加载视网膜图像?有没有比分别加载两个代表并手动组合它们更好的方法?我宁愿不使用 TIFF 作为这些资源的源文件,因为我使用 Acorn 作为我的图像编辑器,而上次我检查时,它并不能很好地理解这样的复合图像格式。

【问题讨论】:

【参考方案1】:

简单的答案是使用 TIFF,您的担心是错误的。在 Xcode 中,设置项目首选项“Combine High Resolution Artwork”,并像现在一样继续使用 Acorn 生成两个 PNG。在构建期间,Xcode 会将这两个 PNG 组合成一个 TIFF,并将其存储在您的包中。

【讨论】:

“合并高分辨率图稿”似乎不会影响文件夹引用。知道如何解决这个问题吗? @BrentRoyal-Gordon - 对不起,我不知道你的最佳答案。要查看的内容包括:包括文件而不是文件夹(您仍然可以使用 Acorn 编辑它们);使用构建阶段脚本来组合和复制文件;并使用嵌套包(添加一个包子项目,将图像放入其中,让 Xcode 构建并复制包 - 听起来可能有点过分,但包只是一个文件夹,它只是让 Xcode 生成文件夹的一种方式)。 HTH【参考方案2】:

我最终硬着头皮在运行时手动组合图像。我通过在 NSImage 上的一个类别中添加这个方法,然后用它代替 -initWithContentsOfURL: 来做到这一点:

- (id)initRetinaImageWithContentsOfURL:(NSURL *)url 
    if((self = [self initWithContentsOfURL:url])) 
        NSURL * baseURL = url.URLByDeletingLastPathComponent;
        NSString * baseName = url.lastPathComponent.stringByDeletingPathExtension;
        NSString * extension = url.lastPathComponent.pathExtension;

        NSString * retinaBaseName = [NSString stringWithFormat:@"%@@2x", baseName];
        NSURL * retinaURL = [baseURL URLByAppendingPathComponent:[retinaBaseName stringByAppendingPathExtension:extension]];

        if([retinaURL checkResourceIsReachableAndReturnError:NULL]) 
            NSData * data = [[NSData alloc] initWithContentsOfURL:retinaURL];
            NSBitmapImageRep * rep = [[NSBitmapImageRep alloc] initWithData:data];

            rep.size = self.size;
            [self addRepresentation:rep];
        
    

    return self;

【讨论】:

【参考方案3】:

这就是我的工作:

NSArray *paths = [NSBundle.mainBundle pathsForResourcesOfType: @"icns" inDirectory: @"Collections/1"];

for (NSString *path in paths) 
    NSString *fileName = [[path lastPathComponent] stringByDeletingPathExtension];
    NSImage  *image = [[NSImage alloc] initWithContentsOfFile: path];
    image.name = fileName;
    [iconCollectionController addObject: @@"icon": image];

但是正如 CRD 已经指出的那样,您需要合并您的作品(作为 tiff 或 icns 文件)。但它使您无需手动选择图像分辨率(这也需要您聆听后备存储的更改)。

【讨论】:

以上是关于从子目录加载视网膜图像的主要内容,如果未能解决你的问题,请参考以下文章

如何从子目录加载张量流中的数据

如何在资产目录新图像集中删除所有 iPhone/iPad 视网膜/非视网膜图像

从子目录加载新站点作为索引

Jasmine Rails,未从子目录加载 src_files

iOS 图像设计(尺寸和资产目录)

资产目录中设备特定图像集中的设备