pbxproj文件主要包含了以下几项主要信息

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

pbxproj文件格式既不是json也不是xml,但是网上已经开源了不少解析该文件的工具,如XcodeProjectJavaAPIpbxplorer等,通过这些工具,我们可以解析pbxproj文件从而获取工程的一些配置信息等。

由于Xcode工具的存在,我们一般不需要与pbxproj直接打交道,通过General、Build Settungs或者Info等面板,就可以完成项目工程配置信息的修改。但是,当涉及到命令行的时候,xcode就显得束手无策。最常见的比如ci的持续集成。通常情况下,大型工程一般由多个开发人员共同开发,而每一个开发人员的开发证书配置文件都有可能不同,特别是当工程中包含Today或者Watch时,配置证书的不同经常会导致ci编译的失败。此时,通过xcode几乎无法解决问题,而在ci编译前,通过修改pbxproj文件证书配置信息就能很好的解决该问题

打开pbxproj文件,涉及到证书配置文件的代码段如下

A05D02521AFFB09600011ADB        /* Debug */        = {      
              isa = XCBuildConfiguration;      
              buildSettings = {      
              ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;      
              CODE_SIGN_IDENTITY =        ""       ;      
              INFOPLIST_FILE = Simple/Info.plist;      
              LD_RUNPATH_SEARCH_PATHS =        "$(inherited) @executable_path/Frameworks"       ;      
              PRODUCT_NAME =        "$(TARGET_NAME)"       ;      
              PROVISIONING_PROFILE =        "4656b587-123a-45bc-a030-bd1a2ewqeqeq"       ;      
              };      
              name = Debug;      
       };

我们需要做的就是在ci编译前用服务器上相应mobileprovision替换PROVISIONING_PROFILE后面的mobileprovision(mobileprovision文件通常以字符串命名),不幸的是,你会发现多行PROVISIONING_PROFILE,而Today和Watch与工程的证书文件都不相同,简单的字符替换已无法区别target。解决方法就是通过A05D02521AFFB09600011ADB这一串编号(姑且叫它编号吧)来区分不同的target

当工程创建的时候,每一个target都有一个相应的编号,并且不会再改变,编号后面/*Debug*/表明这一配置属于Debug Configuration,而ci集成时一般选择release或者distribution,因此,选择对应的编号,其后面的PROVISIONING_PROFILE就是我们需要修改的字符串

filepath=project.pbxproj      
       functhParam(){      
              orgin=$(grep -i -n $1 $filepath | head -n 1 | awk -F        ':'        '{print $1}'       )      
              count=$(grep -i -A 200 $1 $filepath | grep -i -n        'PROVISIONING_PROFILE'        | head -n 1 |awk -F        ':'        '{print $1}'       )      
              let line=$orgin+count-1      
              echo $line      
              sed -i        ''        $line       "s/^.*/$2/g"        $filepath      
       }      
              
       functhParam        "^.*7AD502241505A17900652731.*="        'PROVISIONING_PROFILE = "ace6cb3b-9231-498c-acad-5ea4542f53ff";'

以上脚本的功能就是查找7AD502241505A17900652731编号后面的PROVISIONING_PROFILE,并将该行替换为“ace6cb3b-9231-498c-acad-5ea4542f53ff”表示的mobileprovision配置文件

以上只是修改pbxproj文件的一个应用,如果你想一键修改工程Bundle Identifier,或者你想工程文件夹整理,修改pbxproj都是一种不错的选择,换一换思路,也许路就有了,祝大家玩的愉快!