ReactNative进阶(五十一)project.pbxproj 配置文件详解

文章目录

一、前言

Xcode 中能看见所有的公共配置信息都存在于 project.pbxproj 中。主要包含跟文件相关的 BuildFileGroupFileReference;跟编译相关的 BuildPhaseBuild Configuration(List);以及一些列 TargetTargetDependency

开发者比较关键的信息是配置应用PP文件、包名及APP 版本号。

rust 复制代码
MARKETING_VERSION = 2.4.2;
ONLY_ACTIVE_ARCH = YES;
OTHER_CODE_SIGN_FLAGS = "--deep";
OTHER_LDFLAGS = (
	"$(inherited)",
	"-ObjC",
	"-lc++",
);
PRODUCT_BUNDLE_IDENTIFIER = com.shq5785.com;
PRODUCT_NAME = shq5785;
PROVISIONING_PROFILE_SPECIFIER = "ppFile";

二、project.pbxproj 文件解析

project.pbxproj 文件包含于 Xcode 工程文件 *.xcodeproj 之中,存储着 Xcode 工程的各项配置参数。它本质上是一种旧风格的 Property List 文件,历史可追溯到 NeXT 的 OpenStep。其可读性不如 xmljson,苹果却一直沿用至今,作为一家以创新闻名的公司可能这里剩下的就是情怀吧。

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

可以把整个文件的内容想象成一个字典,字典中的 Key 按照字典序来排列。字典的第一层级总共有 5 个键值对,Key 分别为:archiveVersionclassesobjectVersionobjectsrootObject。其中重要的 KeyobjectsrootObject

所有的配置对象都放在 objects 对应的 Value 中,包括根对象(rootObject)。 objects 对应的 Value 也是一个字典,Key 都为 UUID,Value 依然是个字典。可以将 rootObject 的值(是一个 UUID)作为 Keyobjects 对应的字典中找到根对象。这个根对象的 isa 属性为 PBXProjectisa = PBXProject)。读懂 project.pbxproj 的最好方式就是顺着 rootObject 的各个属性对应的 UUIDobjects 中找到对应的对象,然后一层层看下去。这样整个文件的配置信息存放方式就慢慢摸清了。

objects 的键值对根据内容类型被分成了若干个 section,虽然 section 的顺序是 Xcode 私有 API 钦定的,但每个 section 内部的键值对会根据 Key 的字典序排列。采用注释的方式分节也使得可读性更强。section 的数量跟工程有关,尤其是每个工程的 BuildPhaseTarget 差别都很大。

每个 section 中的对象类型都是相同的,对象的类型是靠 isa 的值区分的。对象内部的属性类型以及含义可以参照这篇文章提供的对照表:[Xcode Project File Format]。(http://www.monobjc.net/xcode-project-file-format.html)

每个对象内部的属性(也是键值对)会把 isa 排在最前面,其余的按照字典序排列。

数组内部的顺序完全按照元素内容的字典序排列。

大概分为以下几类信息:

  • 工程中的文件关联信息、资源关联信息

    • PBXBuildFile 参与编译的文件

    • PBXFileReference 工程中的所有文件信息

  • 文件的组织结构信息

    • PBXGroup 工程中的文件夹
  • 工程的编译配置、证书配置信息

    • PBXResourcesBuildPhase 编译阶段的资源配置

    • PBXFrameworksBuildPhase 编译阶段的framework配置

    • PBXProject 工程信息

    • PBXNativeTarget 工程中所有target的信息

    • XCConfigurationList 每个target下包含的编译模式,如Debug 、 Release等模式

    • XCBuildConfiguration 具体的编译信息,如Release模式下的编译配置

每一项资源在这个文件中都有一个值作为唯一标识,如903C829A2075C24300EB9AD0。可以看做是id。

一般每个ID值后面都会有一个注释来进行说明这个ID对应的具体内容。如903C829C2075C24300EB9AD0 /* TLauncher */,表示这个ID是代表的是TLauncher这个target。

相同类型的资源是按段进行整理的。

每一段内容前用/* Begin xxx section */注释作为开始。用/* End xxx section */ 作为这一段内容的结束。

每一项内容中用isa = xxx 指示该资源所属于的类型。

其中,PBXFrameworksBuildPhasePBXResourcesBuildPhasePBXShellScriptBuildPhasePBXTargetDependencyPBXSourcesBuildPhase这几项内容都是对工程在编译阶段的配置。

对应于工程中如下配置内容:

下面是 objectsPBXNativeTarget section 的一个对象,感受一下格式:

rust 复制代码
/* Begin PBXNativeTarget section */
		00E356ED1AD99517003FC87E /* shq5785Tests */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "mrcsTests" */;
			buildPhases = (
				E813BE00D49641555FA7986E /* [CP] Check Pods Manifest.lock */,
				00E356EA1AD99517003FC87E /* Sources */,
				00E356EB1AD99517003FC87E /* Frameworks */,
				00E356EC1AD99517003FC87E /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
				00E356F51AD99517003FC87E /* PBXTargetDependency */,
			);
			name = shq5785Tests;
			productName = shq5785Tests;
			productReference = 00E356EE1AD99517003FC87E /* shq5785Tests.xctest */;
			productType = "com.apple.product-type.bundle.unit-test";
		};
		13B07F861A680F5B00A75B9A /* shq5785 */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "shq5785" */;
			buildPhases = (
				C8F5F5993094D81A94013E0D /* [CP] Check Pods Manifest.lock */,
				FD10A7F022414F080027D42C /* Start Packager */,
				13B07F871A680F5B00A75B9A /* Sources */,
				13B07F8C1A680F5B00A75B9A /* Frameworks */,
				13B07F8E1A680F5B00A75B9A /* Resources */,
				00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
				605CC81222DD68EB009545B7 /* Embed Frameworks */,
				3A54938F9F6AAF435223E489 /* [CP] Copy Pods Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = mrcs;
			productName = mrcs;
			productReference = 13B07F961A680F5B00A75B9A /* shq5785.app */;
			productType = "com.apple.product-type.application";
		};
		2D02E47A1E0B4A5D006451C7 /* shq5785-tvOS */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 2D02E4BA1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "shq5785-tvOS" */;
			buildPhases = (
				A6B45AA48E3A2F14663044B6 /* [CP] Check Pods Manifest.lock */,
				FD10A7F122414F3F0027D42C /* Start Packager */,
				2D02E4771E0B4A5D006451C7 /* Sources */,
				2D02E4781E0B4A5D006451C7 /* Frameworks */,
				2D02E4791E0B4A5D006451C7 /* Resources */,
				2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = "shq5785-tvOS";
			productName = "shq5785-tvOS";
			productReference = 2D02E47B1E0B4A5D006451C7 /* shq5785-tvOS.app */;
			productType = "com.apple.product-type.application";
		};
		2D02E48F1E0B4A5D006451C7 /* shq5785-tvOSTests */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 2D02E4BB1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "shq5785-tvOSTests" */;
			buildPhases = (
				D14E060D8F1725B6C5A79756 /* [CP] Check Pods Manifest.lock */,
				2D02E48C1E0B4A5D006451C7 /* Sources */,
				2D02E48D1E0B4A5D006451C7 /* Frameworks */,
				2D02E48E1E0B4A5D006451C7 /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
				2D02E4921E0B4A5D006451C7 /* PBXTargetDependency */,
			);
			name = "shq5785-tvOSTests";
			productName = "shq5785-tvOSTests";
			productReference = 2D02E4901E0B4A5D006451C7 /* shq5785-tvOSTests.xctest */;
			productType = "com.apple.product-type.bundle.unit-test";
		};
/* End PBXNativeTarget section */

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

三、证书更换

当更换证书信息时,可按照如下步骤实施。

  1. 首先,通过字符串匹配/* Begin PBXProject section */,找到工程信息内容。

    在该段内容中,通过查找targets字段。找到该工程下的所有target。通过字符串与注释进行匹配,找到需要打包的target的ID值。

  2. 获取到目标target的ID值之后。通过注释,筛选出PBXNativeTarget内容段。

  3. PBXNativeTarget内容段中,找到targetID对应的内容。在这段内容中找到buildConfigurationList字段,获取到这个target下的编译配置列表对象ID。

  4. 此时,进入XCConfigurationList内容段。在该范围中,通过上一步中的编译配置列表对象ID,获取该target下的配置模式列表内容。

  5. 在配置列表中,找到需要使用的模式。拿到该模式对应的配置对象ID值。

  6. 进入XCBuildConfiguration编译配置段。通过上一步中的对象ID值,定位到该配置对象。

  7. 修改该配置对象中的内容。如可以通过修改PROVISIONING_PROFILE等字段的值实现更换证书。

相关推荐
Ya-Jun4 小时前
常用第三方库:flutter_boost混合开发
android·flutter·ios
玫瑰花开一片一片17 小时前
Flutter IOS 真机 Widget 错误。Widget 安装后系统中没有
flutter·ios·widget·ios widget
烎就是我19 小时前
100行代码swift从零实现一个iOS日历
ios·swift
鸿蒙布道师1 天前
鸿蒙NEXT开发通知工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
鸿蒙布道师1 天前
鸿蒙NEXT开发网络相关工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
cauyyl2 天前
xcode 16 遇到contains bitcode
react native·xcode
余生大大2 天前
关于Safari浏览器在ios<16.3版本不支持正则表达式零宽断言的解决办法
ios·正则表达式·safari
爱分享的程序员2 天前
前端跨端框架的开发以及IOS和安卓的开发流程和打包上架的详细流程
android·前端·ios
Macle_Chen2 天前
ios开发中xxx.debug.dylib not found
ios·bug·debug.dylib