了解 Xcode 组和文件夹引用之间的区别

Mar*_*eIV 3 directory xcode grouping

StackOverflow 上有很多地方,这个问题已经被问到并得到了回答。然而,我发现其中的大部分,虽然在技术上是正确的,但遗漏了一些特定的细节,这些细节不仅解释了实际发生的事情,而且在尝试调试文件引用或构建问题时可能是有价值的信息。

我决定根据杰夫·阿特伍德(Jeff Atwood)自己关于鼓励在他说的地方张贴您自己的答案的评论将其发布在这里...

不仅可以提出和回答您自己的问题,而且明确鼓励 [...] 我一直这样做!

因此,我将详细解释这些项目背后究竟发生了什么,希望这些知识可以帮助其他人,因为它对我有帮助,特别是在清除 Xcode 思维的普遍误解方面9,项目树镜像磁盘上的文件夹,实际上并非如此。

Mar*_*eIV 10

深入研究组和文件夹引用

如上所述,这里有很多关于这个主题的答案,所有这些都解释了基本差异。但是,当涉及到行为和对实际发生的事情的理解时,会忽略一些微妙的细节,当您的项目或其更改未按预期工作时,这可能会导致令人沮丧的体验。因此,我将用更彻底的解释将我的帽子扔进戒指。希望这将有助于避免很多头痛。

现在,让我们把手弄脏!

文件夹参考

文件夹引用更容易掌握。它们是指向实际磁盘文件夹的简单指针。磁盘上文件夹中的任何内容都将出现在项目树中。

您可以通过其图标标识文件夹引用,该图标将为蓝色。

通过在项目树中选择文件夹引用,然后在检查器中选择要将其包含在哪个目标中,您可以在应用程序中包含该文件夹中的任何内容。

注意:您只能在文件夹引用级别选择目标,而不能在单个文件级别选择。这是一个全有或全无的添加。

一个重要的副作用是,同时你可以捆绑的资源投入到一个文件夹中引用您的应用程序,您CAN NOT从文件夹中建立参考源代码。源代码必须成组!

团体

而另一方面,群体却更加复杂。在最简单的解释中,它们是 Xcode 项目中的纯逻辑容器,用于存储和组织指向源代码文件的相对指针。这些仅存储在 Xcode 项目中,而不存储在磁盘上。

您可以通过黄色文件夹标识项目中的组。

每个项目,无论是组本身还是组内的文件引用,都指定了一个位置以及它与项目结构的关系。这可以在检查器的“身份和类型”部分找到。

值得注意的是...

  • 可以参考磁盘上的一个特定的文件夹,但不必
  • 文件引用必须指向磁盘上的特定文件。

这些引用的存储方式取决于“位置”的值:

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

在图像上也有细微的差别。如果该组指向实际文件夹,您将只看到黄色文件夹。但是,如果该组未引用特定文件夹(即它是仅逻辑文件夹),您将在文件夹图标中看到一个小三角形。

此外,无论组是否已连接,您始终可以通过查看检查器中的“完整路径”属性来查看组或其任何子项引用的当前物理位置。

同样,重要的是要注意您的逻辑“组”结构与磁盘上的物理结构无关人们经常会错误地认为从 Xcode 9 开始,这种说法是不正确的,但请继续阅读以了解为什么这种误解仍然存在。

如前所述,组并不代表实际的磁盘文件夹。它们是纯粹用于代码组织的简单逻辑分组。但是,它们可以指向实际的磁盘文件夹。您可以通过检查器“身份和类型”部分的“位置”下拉菜单下的小文件夹按钮来设置哪个文件夹。您还可以通过按圆圈中的小 x 再次清除该关联。

现在这里是棘手的部分。在处理不指向实际文件夹的组时,它们的全部目的只是帮助您作为用户以对您有意义的结构组织代码,并使 Xcode 能够解析磁盘上的实际路径那些文件引用。

但是,如果您有一个确实指向文件夹的组呢?那么现在一套全新的规则开始发挥作用。这些规则在 Xcode 9 中发生了变化。

在 Xcode 9 之后,修改组名可能会修改磁盘名称,但不一定。这将如果组名称和物理文件夹名称,这样做比赛前的重命名到。如果他们不这样做,他们的所有意图和目的都是“断开连接”的。

例如,假设您的项目中有一个名为“Virtual”的组,它指向磁盘上名为 Literal 的文件夹,如下所示......

Group      On-disk Folder
-----      --------------
Virtual -> Literal
Run Code Online (Sandbox Code Playgroud)

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

Conceptual -> Literal
Run Code Online (Sandbox Code Playgroud)

如果您随后将“概念”重命名为“文字”,使其与磁盘上的实际文件夹名称相匹配...

Literal -> Literal
Run Code Online (Sandbox Code Playgroud)

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

Changed -> Changed
Run Code Online (Sandbox Code Playgroud)

注意:这与文件夹在磁盘上的位置无关。这仅与名称本身有关,与此无关。

我们去哪?

至于它在磁盘上的位置,事情也比看起来更复杂。如果您移动当前未指向实际磁盘文件夹的组,除了 Xcode 更新它在项目文件中存储项目项的相对路径的方式,使它们相对于更新的组结构之外,不会发生任何事情。

但是,如果您移动当前指向某个文件夹的组——即使它的名称与磁盘上的文件夹不匹配(这是一个关键点,并且经常导致“损坏的”项目树混淆)——它指向的物理磁盘文件夹将被移动到相对于您将其拖到的任何组的新位置,以及磁盘上该文件夹中的所有项目,无论是否在您的项目中引用!

例如,假设您的项目结构中有这个...

Project
   GroupA -> Points to \Code\Project\GroupA
   GroupB -> Points to \Some\Really\Deep\Path\Somewhere\Else\On\The\Disk\Entirely\GroupB
Run Code Online (Sandbox Code Playgroud)

然后将 GroupA 拖到项目树树中的 GroupB 下,就像这样...

Project
   GroupB
       GroupA
Run Code Online (Sandbox Code Playgroud)

由于 GroupA 指向磁盘上的物理文件夹(再次记住,这与组名和目录名是否匹配无关,仅组指向实际目录),磁盘上的目录及其所有内容无论是否被引用都会实际移动到

\Some\Really\Deep\Path\Somewhere\Else\On\The\Disk\Entirely\GroupB\GroupA
Run Code Online (Sandbox Code Playgroud)

同样,您将其移动到目标组的实际磁盘路径下。

现在,如果 GroupB 实际上没有指向文件夹,但 GroupA 指向了文件夹,那么最终位置将解析为 GroupB 在磁盘上解析到的位置,这意味着它会考虑其所有父组来确定位置。

最常见的场景

好消息是,对于 95% 的用例——实际上,除非您正在处理遗留代码库或主动更改新项目的结构——物理磁盘文件夹结构匹配项目结构,并且所有这些文件夹引用都应设置为“相对于组”,这意味着组实质上是文件系统的镜像。 这就是为什么人们认为从 Xcode 9 开始,您正在修改文件系统,但同样,您不是。您仍然只是在修改组和文件引用。只是 Xcode 假设如果您的组结构镜像物理磁盘并且您重命名/重新排序它们,则您可能还希望物理磁盘更新,因此它会为您完成。尽管有点误导,但它非常方便。

有了这些新知识,如果事情变得不正常并且没有像您期望的那样工作,那么可能是时候检查您的文件和组引用以及相关位置了。确保您的文件夹引用实际上指向您期望它们所在的位置,尤其是在升级旧项目时,您应该能够很快回到正轨。

无论如何,希望这更好地解释了事情。肯定帮了我们!:)