NSBundle pathForResource无法找到文件

5

我在“复制束资源”(copy bundle resources)中列出了images.xcassets,之后我尝试仅仅声明文件名MSB_big_icon而不是添加images.xcassets路径。

有人能告诉我我做错了什么吗?

NSString *path = [[NSBundle mainBundle]pathForResource:@"/Raymio_android_images/MSB_big_icon.imageset/MSB_big_icon" ofType:@"png"];
NSLog(@"path: %@", path);
MSBIcon *tilecon = [MSBIcon iconWithUIImage:[UIImage imageWithContentsOfFile:path] error:&error];
3个回答

2
David Ansermot是正确的,xcassets是一种更好的方法,并且强烈推荐使用。如果您不能使用它(例如在旧版本的iOS上运行),仍需将所有内容放在一个目录中,并使用imageNamed:。与手动加载文件相比,这具有重要的缓存优势。 资产目录(xcassets)是管理图像资源的一种(相对较新的)统一方式。这些图像不再作为单独的文件在磁盘上访问。相反,imageNamed:会查询资产目录并获取正确的图像。
在资源目录(asset catalogs)出现之前(对于非图像仍然如此),资源都存储在本地化的目录中。所有未本地化的资源将被放置在名为“Resources”的目录中(无论这些文件在源代码树中的位置如何,以及这些文件在Xcode文件夹中如何排列)。本地化的文件将存储在像“English.lproj”或“French.lproj”这样的目录中。当您调用NSBundle来加载MyImage时,它会按照用户配置的顺序查看每个本地化目录,如果在这些目录中找不到,则会查找Resources目录。
现在,通过在Xcode中将它们标记为目录引用,可以将完整的目录存储为“资源”。在这种情况下,整个目录将被复制到Resources或适当的本地化目录中。要在这样的目录中查找文件,可以使用NSBundle方法的...inDirectory:版本。因此,大多数时候,您只需要使用imageNamed:即可。如果可用,它将从资源目录中获取内容,然后搜索本地化目录,最后再查找Resources。如果您需要查找非图像文件,或者出于某种原因想要获取文件的真实路径,则可以按以下方式计算它:
NSString *path = [[NSBundle mainBundle] pathForResource:@"MSB_big_icon" ofType:@"png"];

如果该资源在目录树中(因为它是Xcode中的目录引用),你可以像这样访问它:
NSString *path = [[NSBundle mainBundle] pathForResource:@"MSB_big_icon"
                                                 ofType:@"png" 
                                            inDirectory:@"Raymio_android_images/MSB_big_icon.imageset"];

也许我只能采用标准方法,但脑海里总有一个声音在嘲讽我没能让它正常工作。我理解错了吗?如果某个文件夹被列在“复制包资源”下,那么这个文件夹就会被添加到bundle中,并可以通过NSBundle使用吗?因为尽管images.xcassets在复制包资源列表中,但使用您的最后一段代码片段仍然无法正常工作。 - DevilInDisguise
但是为什么Xcode会费心将文件和images.xcassets添加到复制包资源中,因为它已经在根文件夹中了,另一方面,根文件夹中有各种文件/文件夹不在复制包中。从您的评论中听起来,复制包资源更多地用于将应用程序外部的某些文件夹添加到应用程序中,对吗?无论如何,我仍然有点困惑为什么这种方法仍然不起作用。 - DevilInDisguise
@DevilInDisguise,我不确定你看到了什么。在构建中的复制文件步骤通常会自动包含所有资源,大多数情况下你无需使用目录来访问这些资源(因为Xcode默认只使用本地化目录结构,不会创建其他目录)。如果你的资源在xcassets中,你肯定不需要使用inDirectory示例。只需使用imageNamed:即可。 - Rob Napier
也许是 image.xcassets 的原因导致我无法使用这个方法?如我在另一个评论中提到的,我已经在使用 imageNamed 方法,但是我想知道为什么我无法通过 imageWithContent... 来定位它。不管怎样,感谢您的帮助。 - DevilInDisguise
是的,如果你把图片放在xcassets中,它们肯定不会在bundle子目录中。 - Rob Napier
显示剩余4条评论

0
这是我其中一个应用程序的代码示例:
NSString *appKey = @"Applications__GENERIC";
NSString *path = [[NSBundle mainBundle] pathForResource:appKey ofType:@"plist"];
appData = [NSDictionary dictionaryWithContentsOfFile:path];

“Applications__GENERIC.plist” 是这样存储的:
enter image description here

其他解决方案: 使用images.xcassets。 然后在您的代码中加载图像,使用以下代码:

UIImage *image = [UIImage imageNamed:@"MyImageWithoutExtension"];

不要加任何路径或扩展名,只写图片的名称


我对+imageWithContentsOfFile很感兴趣,因为它是一个示例应用程序中使用的方法,所以我想知道它是如何工作的(或者不工作)。我已经按照您发布的方式创建了一些图像,但是我仍然想知道为什么我无法使上述内容正常工作。 - DevilInDisguise
扩展名可以添加,因此没有必要建议图像的名称“必须”不带扩展名。 - holex
更新了我的回答。@holex,如果你使用xcassets,你就不需要这样做了。只需要图片资源的名称即可 ;) - David Ansermot

0

尝试使用这个:

NSString *path = [[NSBundle mainBundle] pathForResource:@"MSB_big_icon" ofType:@"png" inDirectory:@"Raymio_android_images/MSB_big_icon.imageset"];

你可以用以下方法调试,即将代码输出到控制台上。
[[NSBundle mainBundle] bundleURL]

然后导航到该文件夹,查看文件夹结构是否与您使用的路径相对应。

我今天也遇到了这个问题,希望它对您也有用。


但是由于images.xcassets被列在复制捆绑资源下,我认为从那个位置开始会更好。同时,我想知道为什么bundlePath返回与bundleURL相同的路径,但使用不同的键。 - DevilInDisguise

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接