迄今为止的路程
我的用例是:
- 我正在跨多个目标同步版本和构建号。
- 我正在将版本和构建号与目标的
Settings.bundle
同步。
- 我正在从 CI 服务器读取并修改构建号。
我以前会将第一点和第二点作为目标构建脚本执行,第三点作为 CI 上的自定义脚本执行。
Xcode 构建设置中存储版本和构建的新方式导致脚本存在问题,因为它们不能有效地修改这些值。至少读取是可能的。
不幸的是,我无法找到一个合法的方法来防止 Xcode 将版本和构建号存储到项目构建设置中,但是我设法创建了一个解决方法。
事实证明,当进行构建或打包时,Info.plist
中写入的值将被使用。这意味着该值在构建时进行替换,这样我们就无法在同一构建时间内修改它。
我还尝试使用 xcodeproj
cli 修改项目,但对项目进行的任何更改都会导致任何构建停止,因此此解决方案无效。
最终,在我尝试的许多不同方法之后,我终于找到了一个妥协方案,它没有违反 Xcode 的新行为。
简短回答:
作为目标预操作,将在执行脚本时将相应的值写入目标的 Info.plist
中的 CFBundleShortVersionString
和 CFBundleVersion
。
作为真相来源,我使用 Xcode 构建设置来读取所需目标的 MARKETING_VERSION
和 CURRENT_PROJECT_VERSION
值。
这样,当您从项目设置中修改值时,下一次构建/打包时,它们将被写入 Info.plist
,从而允许您的任何现有脚本逻辑继续工作。
详细回答
唯一可以在构建操作中修改资源的方法是使用 pre-action
脚本。如果您尝试从构建脚本进行修改,则更改不会立即生效,并且不会在构建/打包结束时存在。
要添加预构建操作,请转到“编辑方案”。
![enter image description here](https://istack.dev59.com/eCnB6.webp)
然后展开“构建”和“存档”部分。在 Pre-action
下,单击 Provide build and settings from
下拉菜单,并选择您希望读取值的真实来源目标。
请添加以下脚本:
![输入图像描述](https://istack.dev59.com/WTh18.webp)
将以下脚本添加进去:
cd ${PROJECT_DIR}
exec > Pruvit-Int.prebuild.sync_project_version_and_build_with_info_plists.log 2>&1
./sync_project_version_and_build_with_info_plists.sh $MARKETING_VERSION $CURRENT_PROJECT_VERSION
这些脚本执行以下操作:
- 进入同步脚本所在目录以执行它。
- 允许在预处理操作期间编写日志,否则默认情况下将关闭任何输出。
- 通过提供
MARKETING_VERSION
和 CURRENT_PROJECT_VERSION
来执行同步脚本。
最后一步是编写自己的同步脚本,读取所提供的
MARKETING_VERSION
和
CURRENT_PROJECT_VERSION
的值到相应的目标,并在其他需要的时候进行同步。
在我的情况下,脚本如下:
#!/bin/bash
#IMPORTANT - this script must run as pre-action of each target's Build and Archive actions
version_number=$1
build_number=$2
echo "version_number is $version_number"
echo "build_number is $build_number"
#update Pruvit/Info.plist
pruvitInfoPlist="Pruvit/Info.plist"
/usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString $version_number" $pruvitInfoPlist
/usr/libexec/PlistBuddy -c "Set CFBundleVersion $build_number" $pruvitInfoPlist
#update Pruvit/Settings.bundle
settingsPlist="Pruvit/Settings.bundle/Root.plist"
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:DefaultValue $version_number" $settingsPlist
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $build_number" $settingsPlist
#update BadgeCounter/Info.plist
badgeCounterInfoPlist="BadgeCounter/Info.plist"
/usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString $version_number" $badgeCounterInfoPlist
/usr/libexec/PlistBuddy -c "Set CFBundleVersion $build_number" $badgeCounterInfoPlist
我在我的两个应用目标之间使用共享的
Info.plist
和
Settings.bundle
,因此我只需要更新一次。
此外,我还使用了一个通知服务扩展BadgeCounter
,它必须与嵌入它的目标具有完全相同的版本和构建。所以我也要更新这个。
plistbuddy
修改属性列表是清晰简洁的,而修改项目文件则更加混乱、不可靠,并容易导致文件格式意外发生变化。 - hotdogsoup.nl