深入探讨:了解Xcode组和文件夹引用之间的区别

kuarbcqp  于 2023-03-24  发布在  其他
关注(0)|答案(1)|浏览(141)

在StackOverflow上的很多地方,这个问题已经被问过和回答过了。然而,我发现大多数人,虽然技术上是正确的,但遗漏了一些具体的细节,这些细节不仅解释了实际发生的事情,而且在试图调试文件引用或构建问题时可能是有价值的信息。
我决定在这里张贴这每杰夫阿特伍德的own comments on encouraging posting your own answers他说...
问和回答你自己的问题不仅仅是可以的,这是明确鼓励的[...]我一直都这样做!
因此,我添加了一个详细的解释,这些项目的幕后到底发生了什么,希望这些知识可以帮助其他人,因为它帮助了我,***特别是在清除Xcode 9中常见的误解方面,项目树反映了磁盘上的文件夹,实际上并非如此。

xxhby3vn

xxhby3vn1#

深入了解组和文件夹引用

如上所述,SO上有很多关于这个主题的答案,所有这些都解释了基本的差异。然而,当涉及到行为和对实际情况的理解时,有一些微妙的细节被忽略了,这可能会导致当你的项目或其更改没有按预期工作时令人沮丧的体验。因此,我将抛出我的帽子进入一个更彻底的解释环。希望这将有助于避免很多头痛。
现在,让我们把手弄脏!

文件夹引用

文件夹引用是两者中比较容易掌握的。它们是指向实际磁盘上文件夹的简单指针。文件夹引用可以通过它的蓝色图标来识别。
文件夹引用跟踪对引用文件夹内容的添加、重命名和删除,根据需要自动更新项目树,即使这些更改是在Xcode之外进行的。
通过文件夹引用的蓝色图标标识文件夹引用。
文件夹引用的主要用途是将其内容作为任何选定目标的捆绑资源包括在内。
有关定位文件夹引用的重要事项:
1.您只能在文件夹引用级别选择目标,而不能在单个文件或子文件夹级别选择目标。这是一个全有或全无的附加操作。
1.文件夹引用中的任何源代码文件都只是作为文件资源添加到bundle中,就像任何其他文件一样。它们***不能***从文件夹引用中编译。如果你想编译代码,它 * 必须 * 在组中!
最后一点一开始可能看起来很奇怪/令人困惑,因为您在目标中包含了源代码,但实际上它并没有被编译。(或目标)上的文件夹引用实际上是在说“将此文件夹中的所有内容作为捆绑资源包括在内”,而不管这些文件是什么。但是编译那个'会混淆'这个文件夹代表捆绑的资源'这句话的简单性。
因此,如果您希望代码被编译,则它必须在一个组中。

群组

另一方面,组要复杂得多。最简单的解释是,它们是Xcode项目中的逻辑容器,用于存储和组织指向源代码文件的相对指针。这些指针只存储在Xcode项目中,而不是存储在磁盘上。
您可以通过黄色文件夹标识项目中的组。
每个项目,无论是组本身还是组中的文件引用,都指定了一个位置以及它与项目结构的关系。这可以在检查器的“标识和类型”部分找到。
值得注意的是...

  • 组***可以***引用磁盘上的特定文件夹,但不必
  • 文件引用***必须***指向磁盘上的特定文件。

这些引用的存储方式取决于'Location'的值:

  • 如果“Location”设置为“Absolute Path”,则引用将包含该项目的整个磁盘路径。
  • 如果它被设置为“相对于组”,那么它首先确定组当前解析到的值,然后引用相对于该值存储。这将通过父组递归地向上传播。

在图标上也有一个微妙的区别。如果组指向一个实际的文件夹,你只会看到黄色的文件夹。但是,如果组没有引用一个特定的文件夹(即它是逻辑上的),你会在文件夹的图标中看到一个小三角形。
此外,无论组是否已连接,您都可以通过查看检查器中的“完整路径”属性来查看组或其子组引用的当前物理位置。
再次强调,需要注意的是,逻辑“组”结构***与磁盘上的物理结构***毫无关系。***人们经常犯这样的错误,认为从Xcode 9开始,这种说法是不正确的,但请继续阅读,了解为什么这种误解仍然存在。
如上所述,组并不代表实际的磁盘上的文件夹。它们是纯粹用于代码组织的简单逻辑分组。但是,它们可以 * 指向 * 实际的磁盘上的文件夹。您可以通过检查器的“标识和类型”部分中的“位置”下拉列表下的小文件夹按钮设置哪个文件夹。您也可以通过按圆圈中的小x再次清除该关联。
这里有一个棘手的部分。当处理不指向实际文件夹的组时,它们的全部目的只是帮助用户以一种对您有意义的结构组织代码,并让Xcode能够解析磁盘上这些文件引用的实际路径。
但是如果你有一个组指向一个文件夹呢?现在一套全新的规则开始起作用了。这些规则是Xcode 9中改变的。

在Xcode 9之后,修改组名可能会修改磁盘上的名称,但不一定只有在重命名***之前组名和物理文件夹名***匹配时才会这样做。如果不匹配,它们实际上是“断开连接”的。
例如,假设您的项目中有一个名为“Virtual”的组,它指向磁盘上名为Literal的文件夹,如下所示...

Group      On-disk Folder
-----      --------------
Virtual -> Literal

如果将组“Virtual”重命名为“Conceptual”,则磁盘上不会发生任何操作。

Conceptual -> Literal

如果您将'Conceptual'重命名为'Literal',使其与磁盘上的实际文件夹名称匹配...

Literal -> Literal

...然后再次将'Literal'重命名为'Changed',组 * 和 * 文件夹都将更新为'Changed'。

Changed -> Changed

注意:这与文件夹在磁盘上的位置无关。这只与名称本身有关,没有其他关系。

我们要去哪里

至于它在磁盘上的位置,事情也比看起来更复杂。如果你移动一个当前没有指向实际磁盘文件夹的组,除了Xcode更新它在项目文件中存储项目的相对路径之外,什么也不会发生,使它们相对于更新的组结构。
但是,如果您移动当前指向某个文件夹的组-即使其名称与磁盘上的文件夹不匹配(这是一个关键点,也是一个经常引起混淆的“损坏的”项目树)--它所指向的物理磁盘文件夹将被移动到相对于您将其拖到的任何组的新位置沿着磁盘上该文件夹中的所有项目***,无论是否在项目中引用!***
例如,假设您的项目结构中有以下内容...

Project
   GroupA -> Points to \Code\Project\GroupA
   GroupB -> Points to \Some\Really\Deep\Path\Somewhere\Else\On\The\Disk\Entirely\GroupB

然后拖动GroupA,使其位于项目树中的GroupB下,就像这样……

Project
   GroupB
       GroupA

由于GroupA指向磁盘上的一个物理文件夹(同样,请记住,这与组名和目录名是否匹配无关,只是组指向一个实际的目录),因此磁盘上的目录及其所有内容(无论是否被引用)实际上都将物理移动到

\Some\Really\Deep\Path\Somewhere\Else\On\The\Disk\Entirely\GroupB\GroupA

同样,您将它移动到目标组的 * 实际 * 磁盘路径下。
现在,如果GroupB实际上没有指向文件夹,但GroupA指向,则最终位置 resolves 到GroupB在磁盘上解析到的位置,这意味着它会考虑其所有父组来确定位置。

最常见场景

好消息是,对于95%的用例--真的,除非你处理的是遗留代码库,或者你主动改变了一个新项目的结构--物理磁盘上的文件夹结构 * 将 * 匹配项目结构,所有这些文件夹引用都应该设置为“相对于组”,这意味着组本质上是镜像文件系统。你正在修改文件系统,但同样,你没有。你仍然只是修改组和文件引用。***这只是Xcode假设,如果你的组结构镜像物理磁盘,你重命名/重新排序它们,很可能你也希望物理磁盘更新,所以它为你做了这件事。这是非常方便的,尽管有点误导。
有了这些新知识,如果事情变得不正常,并且没有像你期望的那样工作,那么可能是时候检查你的文件和组引用以及相对位置了。确保你的文件夹引用实际上指向你期望的位置,特别是在升级旧项目时,你应该能够很快回到正轨。
无论如何,希望这能更好地解释事情。当然对我们有帮助!:)

相关问题