在使用imageNamed
创建UIImage
时,使用NSBundle
方法pathForResource
搜索图像路径有多重要?我看到一些教程代码只直接指定图像名称,还有一些则需要先查找路径。
从我的经验来看,我总是直接使用名称,这样做通常都能正常工作。我认为它会自动知道如何找到图像。在什么情况下需要更进一步查找路径呢?这个问题的重要性是什么?
在使用imageNamed
创建UIImage
时,使用NSBundle
方法pathForResource
搜索图像路径有多重要?我看到一些教程代码只直接指定图像名称,还有一些则需要先查找路径。
从我的经验来看,我总是直接使用名称,这样做通常都能正常工作。我认为它会自动知道如何找到图像。在什么情况下需要更进一步查找路径呢?这个问题的重要性是什么?
根本不需要...是回答原问题的答案:
在使用imageNamed创建UIImage时,使用NSBundle方法pathForResource搜索图像路径有多重要?
并不重要...这是Zoul和Ranga所接受的答案以及其他答案的正确性。公平地说,如果你谈论应用程序包目录结构,或者图像在Xcode“蓝色”文件夹中(稍后会提到更多),则它们是正确的,但对于大多数情况而言并不是。
无论如何,让我们来看看真正的答案。
像往常一样,我在寻找自己的答案时发现了这个问题。 我从未找到文档或其他回答令人满意的答案,因此我决定进行测试。
我的测试细节都在下面,但是让我在这里总结一下结果。
简而言之,当使用imageNamed:加载图像时,取决于您放置它们的位置:
如果您的图像位于项目的根目录中,即使以纯逻辑Xcode组织,那么不需要考虑路径:只需图像名称。
如果您的图像位于附加到文件系统目录的组中,通过“为添加的文件夹创建组”,则仍然无需担心名称。
如果您的图像位于“蓝色”组中,该组通过“为添加的文件夹创建文件夹引用”附加到文件系统目录,则可以像上面接受的答案建议的那样指定相对路径来使用imageNamed:加载它。
如果您使用imageWithContentsOfFile:作为imageNamed:的主要替代方法,则确实需要完整的文件路径,包括捆绑路径,这意味着您需要知道Xcode导航器结构如何转换为捆绑目录结构中的路径。
这两种方法之间的其他重要区别:
接下来是我的测试过程。
我创建了一个简单的UITableView应用程序,并使用不同的方法在表的行中显示3个简单图标文件。这些图标在Xcode项目结构中的位置不同。需要注意的是,重点在于Xcode。理解对原始问题的回答的关键是,在iOS应用程序中有三种完全不同的项目目录结构:你在Xcode导航器中看到的目录结构,你在Finder中看到的相同项目的文件系统上的目录结构(右键单击Xcode导航器中的任何项,然后选择“在Finder中显示”),以及你很少看到的部署应用程序的 "bundle" 目录结构。你也可以在Finder中找到这最后一个 - 通过在 ~/Library/Application Support/iPhone模拟器中找到你的应用程序,并深入到.app目录中。我待会儿会给你展示一张图片。
因此,在我的应用程序中,我以不同的方式将所有三个图标png图像文件拖入Xcode中:
icon1.png(一个时钟),我将其作为文件拖到Xcode项目的根目录中,后来我创建了一个新组并将其拖入其中。这个组在文件系统中没有任何目录表示:它是一个纯粹的Xcode组。因此它的名称是:“JustGroup”。
icon2.png(一只眼睛),我最初将我的文件系统放在名为“RealDir”的目录中,并将整个目录拖入Xcode,当询问时,我选择了“为添加的任何文件夹创建组”选项。这意味着Xcode中的RealDir组附加到文件系统中名为RealDir的实际目录(在我的项目目录中),而icon2.png就在其中。
icon3.png(一个目标),我也放在了一个单独的目录中,然后将其拖入Xcode。只是这一次,我选择了第二个单选按钮“为添加的任何文件夹创建文件夹引用”。这会在Xcode中创建一个所谓的“蓝色”组。稍后会详细介绍这是什么意思。我将该组(以及目录)命名为“FolderReference”。
这里是Xcode给你的选项截图:
这是我在Xcode中的项目结构:
现在,在我的应用程序中,我使用了两种方法来加载每个图标:UIImage imageNamed:和UIImage imageWithContentsOfFile。我创建了一堆行,每个单元格的标题都是包含图标的组的名称:JustGroup、RealDir或FolderReference,以及所使用的方法的名称:imageNamed与fromFile(我使用它作为imageWithContentsOfFile的缩写)
单元格的详细标签(标题下面的淡色文本)显示了我给该方法指定的文件或路径名。
要清楚,在“fromFile”的情况下,我将“相对”名称与包路径相加。因此,对于“fromFile”,我实际上使用的是以下代码:
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *imagePath = [NSString stringWithFormat:@"%@/%@", bundlePath, filePath];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
“filePath”是您在表单单元格详细标签中看到的路径。另一方面,在imageNamed:中,单元格详细信息中的filePath会原样传递。
而行上的image自然是加载的图像。因此,在表格中没有图像的行中,图像加载失败。
简而言之,这里是结果。如果您没有阅读此帖子,请至少浏览一下此图片,它将告诉您所需的所有内容。
以下是易于理解的基本说明:
正如官方文档中所述,imageNamed:方法从应用程序捆绑包中加载图像。这意味着您不需要指定捆绑包位置,只需要指定文件名。甚至仅需要文件的基本名称。文档在这里有点薄弱,应该明确表示它从给定文件路径相对于应用程序捆绑包根目录加载图像。
(这是关键,请注意)关于捆绑目录的规则,指的是您部署的应用程序捆绑包中的根目录。如果您进行探索,这意味着位于“.app”目录本身中。那不是Xcode导航器中Xcode项目的根目录,也不是Finder中Xcode项目的根目录。
这是因为,在将应用程序部署到设备(或模拟器)时,所有由“添加文件夹的组”表示的项目目录都会被扁平化。也就是说,该目录被忽略了,并且所有内容都被毫不客气地倾倒到捆绑包的根目录中。(我说“毫不客气”,因为如果不同文件夹中存在具有相同名称的文件,则它们将在此处碰撞,并且您将得不到任何帮助来解决导致问题的原因。)这是我示例中RealDir的情况:在部署的应用程序中,RealDir不再存在,而icon2.png留下来与其他人混在一起(可怕)。几乎可以毫不费力地说,“JustGroup”,纯逻辑的Xcode组,也被忽略了——它从来不是真正的目录,只是Xcode用户的视觉辅助——而icon1.png也在捆绑包根目录中。
这就是为什么imageNamed:能够加载icon2的原因。
也是为什么imageWithContentsOfFile无法在“RealDir/image2.png”中找到它的原因:因为部署的应用程序中没有RealDir目录。
"蓝色文件夹",也就是用"添加文件夹的引用"表示的目录,实际上被保留在应用程序捆绑目录结构中。这似乎是蓝色文件夹的重点:它们为您提供了一种在部署的应用程序中创建目录结构的方法。我不确定最初的理由是什么,但一个很好的用例是当您有几个包含同名资源文件的替代版本的目录,并且您希望您的应用程序能够通过更改目录在运行时在它们之间进行切换。无论如何,在我的FolderReference中的icon3.png文件在部署的应用程序中仍然保留在我的FolderReference目录中。
为了澄清,这是我的文件夹结构:
你看到了我的Xcode项目导航器结构,这是它下面的文件系统目录:
最后,也许最重要的是,部署的捆绑文件系统目录结构:
注意:我在我的Mac上找到了这个位置:您可以在类似的位置找到您的位置-您可能需要搜索一下,找到哪个丑陋的GUID命名的子目录包含您的应用程序。
~/Library/Application Support/iPhone Simulator/5.1/Applications/4EB386B2-CD7E-4590-9757-18DDDEE6AF4F/ImageLoadingTest.app
希望这能帮到你。测试、探索,最后描述它确实对我有所帮助。
foo / image.png
和 bar / image.png
时。我不知道 [UIImage imageNamed:@“foo / image”]
是否有效,但这很容易尝试。UIImageView* imageView=[[UIImageView alloc] initWithFrame:CGRectMake(50, 100, 16, 16)];
UIImage *image = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@"Images/Wall1" ofType:@"png"]];
imageView.image = image;
UIImageView* imageView=[[UIImageView alloc] initWithFrame:CGRectMake(50, 100, 16, 16)];
UIImage *image = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@"Wall1" ofType:@"png"]];
imageView.image = image;
[self.view addSubview:imageView];
在我的手机上运行应用程序,图像无法显示
在[self.view addSubview:imageView];处添加断点;
图像为空
打开终端并更改目录到我的项目,Wall1.png不是组文件夹Images。从项目中删除png,创建一个Images文件夹,将Wall1.png移动到该文件夹中。将现有文件Wall1.png添加到组Images中。
运行应用程序,图像仍然无法显示。
图像为空
将Images/Wall1更改为Wall1
运行应用程序,瞬间图像就显示出来了
如果您为图像创建了一个组,则Xcode不会创建相应的目录。如果您想要(我更喜欢将我的图像放在单独的文件夹中),请手动创建一个。在使用UIImage imageWithContentsOfFile时,请勿指定图像文件的完整路径。
试试这个。
[UIImage imageNamed:@"your directory path of image"]
[UIImage imageNamed:@"Dir1/folder1/folder2/imagename.jpeg"]