iOS 开发 xcode中的project.pbxproj--深入剖析

本文详细探讨了iOS开发中Xcode项目文件project.pbxproj的起源、结构和解析,阐述了其在版本控制中导致冲突的原因,如位置变化、文件重命名和移动。理解project.pbxproj对于解决Git/SVN冲突和优化协作流程至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

iOS 开发 xcode中的project.pbxproj–深入剖析

1.前言

  1. xcode将我们对项目的配置信息,统一写到了project.pbxproj文件里,一般情况下,我们是不需要直接和project.pbxproj打交道的,我们通过编辑xcode里面的选项,如buildsetting,general来修改pbxproj文件

  2. 用git/svn等工具协作时,经常遇到project.pbxproj冲突.每次这么处理都很麻烦,很多时候度娘也解决不了,导致团队开发时一部分时间浪费在了解决冲突上.大型工程一般由多个开发人员共同开发,而每一个开发人员的开发证书配置文件都有可能不同,配置证书的不同经常会导致编译的失败。此时,通过xcode几乎无法解决问题,而在编译前,通过修改pbxproj文件证书配置信息就能很好的解决该问题

  3. 所在位置–选中工程文件,右键单击,显示包内容
    这里写图片描述
    双击project.pbxproj文件
    这里写图片描述

Xcode打开project.pbxproj文件—是不是看起来很苦涩的感觉

这里写图片描述

  • Xcode的工程文件是 工程名.xcodeproj,而它其实是个package目录,通过显示包内容,可以查看到它内部主要有project.pbxproj 和 xcuserdata。其中,xcuserdata 一般是跟用户相关的一些设置,如断点 记录等,一般不用放到版本管理中。而project.pbxproj 是工程描述文件,描述了工程里的源码文件、schema设置等。它的格式是文本类型的plist(Info.plist是binary plist),里面是一个一个的object,具体的各种object定义可以参见文末给出的链接。

  • project.pbxproj 的合并历来都是代码版本管理的噩梦。特别是当代码框架进行重构时,纯手工合并,简直就是不要不要的。

2. project.pbxproj 由来##

  1. project.pbxproj 文件被包含于 Xcode 工程文件 *.xcodeproj 之中,存储着 Xcode 工程的各项配置参数。它本质上是一种旧风格的 Property List 文件,历史可追溯到 NeXT 的 OpenStep。其可读性不如 xml 和 json,苹果却一直沿用至今

  2. Property List 有很多种表现方式,最古老的格式就是之前提到的 NeXTSTEP 所使用的格式。与 json 最明显的差别是:数组用小括号括起来并用逗号隔开元素;字典用大括号括起来并用分号隔开键值对,键值之间用等号连接;二进制数据用尖括号 括起来:
    数组:
    ( "1", "2", "3" )
    字典:
    { "key" = "value"; ... }
    这也是 project.pbxproj 文件中所使用的格式。

  3. Property List 在苹果家族的历史上存在三种格式:OpenStep,XML 和 Binary。除了 OpenStep 被废弃不支持写入以外,其余格式都提供 API 支持读写。

3. 简要解析 project.pbxproj 文件

3.1内容规则

  1. project.pbxproj 使用 UUID 作为交叉引用的索引,保证每个配置信息对象的唯一性。因为 UUID 根据机器硬件和时间戳生成,避免了多人在同一时间段操作修改工程文件带来的问题。也就是说工程中每项配置对象都有个唯一的 UUID,然后其他配置对象想引用某个配置对象直接使用它的 UUID 即可。

  2. 可以把整个文件的内容想象成一个字典,字典中的 Key 按照字典序来排列。字典的第一层级总共有 5 个键值对,Key 分别为:archiveVersion,classes,objectVersion,objects 和 rootObject。其中重要的 Key 是 objects 和 rootObject。

  3. 所有的配置对象都放在 objects 对应的 Value 中,包括跟对象(rootObject)。 objects 对应的 Value 也是一个字典,Key 都为 UUID,Value 依然是个字典。可以将 rootObject 的值(是一个 UUID)作为 Key 在 objects 对应的字典中找到根对象。这个根对象的 isa 属性为 PBXProject(isa = PBXProject)。

注意:

  • 读懂 project.pbxproj 的最好方式就是顺着 rootObject 的各个属性对应的 UUID 在 objects 中找到对应的对象,然后一层层看下去。这样整个文件的配置信息存放方式就慢慢摸清了。
  • objects 中的键值对被分成了若干个 section,虽然 section 的顺序是 Xcode 私有 API 钦定的,但每个 section 内部的键值对会根据 Key 的字典序排列。
  • 每个对象内部的属性(也是键值对)会把 isa 排在最前面,其余的按照字典序排列。
  • 数组内部的顺序完全按照元素内容的字典序排列。

下面是 objects 中 PBXNativeTarget section 的一个对象,感受一下格式:

/* Begin XCConfigurationList section /
62BD7B3B1D990B4100B3F7BB /
Build configuration list for PBXProject “jinDuGold” / = {
isa = XCConfigurationList;
buildConfigurations = (
62BD7B551D990B4100B3F7BB /
Debug /,
62BD7B561D990B4100B3F7BB /
Release /,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
};
62BD7B571D990B4100B3F7BB /
Build configuration list for PBXNativeTarget “jinDuGold” / = {
isa = XCConfigurationList;
buildConfigurations = (
62BD7B581D990B4100B3F7BB /
Debug /,
62BD7B591D990B4100B3F7BB /
Release /,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
};
/
End XCConfigurationList section /
};
rootObject = 62BD7B381D990B4100B3F7BB /
Project object */;
}

可以根据 62BD7B381D990B4100B3F7BB 找到对应的 buildConfigurationList 对象的内容,所以说 project.pbxproj 使用 UUID 作为交叉引用的索引。通过这种关系,可以递归构建一张有向图,每个对象都是一个节点。

3.2 内容类型

 - 工程文件关联信息,如PBXBuildFile、PBXFileReference
 - 组织结构分类信息,如PBXGroup
 - 项目工程配置信息,如XCBuildConfiguration、XCConfigurationList

objects 的键值对根据内容类型被分成了若干个 section,采用注释的方式分节也使得可读性更强。section 的数量跟工程有关,尤其是每个工程的 BuildPhase 和 Target 差别都很大。下面列出了一个section 列表(非完整):
![这里写图片描述](https://img-blog.csdn.net/20161031215019857)
每个 section 中的对象类型都是相同的,对象的类型是靠 isa 的值区分的。对象内部的属性类型以及含义可以参照这篇文章提供的对照表:点击--[Xcode Project File Format](http://www.monobjc.net/xcode-project-file-format.html)

##4. 常见的冲突##

pbxproj文件冲突,主要是在跟文件相关的object的合并上。跟文件相关的object,主要就是上面具体描述的那几种类型:

  1. PBXFileReference
  2. PBXBuildFile
  3. PBXSourcesBuildPhase
  4. PBXResourcesBuildPhase
  5. PBXGroup
造成冲突的原因主要有:

 - 位置变化:一般来说,除了PBXGroup 中文件是按实际的位置(比如在Xcode中的某个group中,把文件拉到前面的位置,那么它在pbxproj中的位置就在前面),其他的几个基本上跟文件的创建时间有关系,后面创建的文件,对应产生的PBXBuildFile 等对象就排在后面。但是,文件一多,再通过多人操作,PBXBuildFile 等对象的顺序往往就没规律了。虽然大多数object相同,但是由于它们在两边的位置不同,导致diff时比较困难。

 - 文件重命名,导致文件名不同
在Xcode中对文件重命名后,相关的uuid并不会变化。只是对应的注释中的文件名发生变化。

 - 移动文件,导致uuid变化:这里说的移动,指的是删除文件,并重新添加到工程。如项目重构时,可能要建立子目录,并把相应文件删除,并重新添加。移动文件后,对应的uuid肯定变了,但是注释中的文件名还是一样的。

 - 新增文件:会在PBXBuildFile 等分区中添加相应的对象。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值