8. Xcode 工程文件解析

本文详细探讨了Xcode的工程文件结构,包括xcworkspace和xcodeproj的组成,特别是xcodeproj中的Property List、project.pbxproj以及Xcode Object Identifiers。通过解析,揭示了Xcode如何通过PBXFileReference和PBXGroup管理文件和资源,并介绍了如何通过代码编辑Xcode工程,如添加源文件和编译依赖。
摘要由CSDN通过智能技术生成

be629a63be6b7d944444bc86a9f78833.png

引子

「Molinillo 依赖校验」通过后,CocoaPods 会根据确定的 PodSpec 下载对应的源代码和资源,并为每个 PodSpec 生成对应的 Xcode Target。本文重点就来聊聊 Xcode Project 的内容构成,以及 xcodeproj[1] 是如何组织 Xcode Project 内容的。

Xcode 工程文件

早在前文「Podfile 的解析逻辑」中,我们简单介绍过 Xcode 的工程结构:Workspace、Project、Target 及 Build Setting 等。

a6eaf878ceb0c06482601b198eb749a1.png

我们先来了解下这些数据在 Xcode 中是如何表示,了解这些结构才能方便我们理解 xcodeproj 的代码设计思路。

xcworkspace

早在 Xcode 4 之前就出现 workspace bundle 了,只是那会 workspace 仍内嵌于 .xcodeproj 中。Xcode 4 之后,我们才对 workspace 单独可见。让我们新建一个 Test.xcodeproj 项目,来看看其目录结构:

Test.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│   ├── contents.xcworkspacedata
│   └── xcuserdata
│       └── edmond.xcuserdatad
│           └── UserInterfaceState.xcuserstate
└── xcuserdata
    └── edmond.xcuserdatad
        └── xcschemes
            └── xcschememanagement.plist

可以发现 Test.xcodeproj bundle 内包含 project.workspace。而当我们通过 pod install 命令成功添加 Pod 依赖后,Xcode 工程目录下会多出 Test.workspace,它是 Xcodeproj 替我们生成的,用于管理当前的 Test.projectPods.pbxproj。新建的 workspace 目录如下:

Test.xcworkspace
└── contents.xcworkspacedata

生成的 workspace 文件夹内部只包含了 contents.xcworkspacedata,为 xml 格式的内容:

<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "group:Test.xcodeproj">
   </FileRef>
   <FileRef
      location = "group:Pods/Pods.xcodeproj">
   </FileRef>
</Workspace>

在标签 Workspace 下声明了两个 FileRef 其地址分别指向了 Test.xcodeprojPods.xcodeproj。这里注意的是 FileRef 属性的值使用前缀 group + path 来修饰的,而内嵌的 project.xcworkspace,使用 self 作为前缀:

<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "self:">
   </FileRef>
</Workspace>

另外,当我们用 Xcode 打开项目后,能发现 workspace 目录下会自动生成 xcuserdata 目录,它用于保存用户的 Xcode 配置。比如:

  • UserInterfaceState.xcuserstate:以二进制的 Plist 保存,用于记录窗口布局等个性化设置。

  • xcdebugger:记录各种断点数据。

这也是在日常开发中,经常会选择将 xcuserdata 目录 ignore 掉的原因。

xcodeproj

.xcworkspace 类似 .xcodeproj 同为 Xcode 工程配置的 bundle,接下来重点展开 project.pbxproj,它记录了 Xcode 工程的各项配置,本质上是一种旧风格的 Plist 文件。

Property List

Plist 被设计为人类可读的、可以手工修改的格式,故采用了类似于编程语言的语法将数据序列化为ASCII数据。Plist 最早可追溯到 NeXTSTEP 时期,由于历史原因,目前它支持多种格式,string、binary、array、dictionary 等类型数据。相比于 JSON,Plist 还支持二进制数据的表示,以 <> 修饰文本形式的十六进制数,其中字典与数组的区别如下:

Array:
plist => ( "1", "2", "3" )
json => [ "1", "2", "3" ]

Dictionary:
plist => { "key" = "value"; ... }
json => { "key" : "value", ... }

处理 Plist 文件可使用 Unix 提供的 plutil 工具。比如将 Plist 文件转成 XML 格式:

plutil -convert xml1 -s -r -o project.pbxproj.xml project.pbxproj

-convert fmt 选项支持转换的格式有:xml1、binary1、json、swift、json。

project.pbxproj

pbxproj 文件全称为 Project Builder Xcode Project,光看第一层元数据比较简单:

// !$*UTF8*$!
{
 archiveVersion = 1;
 classes = {
 };
 objectVersion = 50;
 objects = {
  ...
   };
 rootObject = 8528A0D92651F281005BEBA5 /* Project object */;
}

文件以明确的编码信息开头,archiveVersion 通常为 1,表示序列化的版本号;classes 则似乎一直为空;objectVersion 表示所兼容的最低版本的 Xcode,该数字与 Xcode 的版本对应关系如下:

53 => 'Xcode 11.4',
52 => 'Xcode 11.0',
51 => 'Xcode 10.0',
50 => 'Xcode 9.3',
48 => 'Xcode 8.0',
47 => 'Xcode 6.3',
46 => 'Xcode 3.2',
45 => 'Xcode 3.1',

rootObject 记录的 16 进制数字,为 project 对象的索引。这里我们可以称其为 Xcode Object Identifier,pbxproj 中的每个 Xcode Object 创建时,都会生成对应唯一标识数字,而上面的 objects 字典则记录了整个 Xcode 项目的所有 Xcode Object。

Xcode Object Identifiers

Xcode Object Identifier 是用 24 位的 16 进制字符表示,我们暂且称其为 GUID。

⚠️ 注意这并不意味着它与其他称为 GUID 的其他事物相似。

生成的 GUID 不仅在项目文件中必须唯一,并且在 Xcode 中同时打开的其他项目文件中也必须唯一,即跨工程唯一性。只有这样能避免了多人合作中,同时新增或编辑工程文件带来的问题。这其实是一个有趣的竞争需求,有兴趣的可以查看 Premake[2] 这个项目,它能保证重新生成的项目具有相同的 GUID。

对于 Xc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值