如何使用脚本读取 Xcode 11 中的当前应用程序版本
How to read current app version in Xcode 11 with script
直到 Xcode 11,我使用了一个脚本来读取当前应用程序版本(对于 AppStore)并帮助我更改 LaunchScreen,因为我们无法使用swift 为此。
sourceFilePath="$PROJECT_DIR/$PROJECT_NAME/App/Base.lproj/LaunchScreen.storyboard"
versionNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$INFOPLIST_FILE")
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
sed -i .bak -e "/userLabel=\"APP_VERSION_LABEL\"/s/text=\"[^\"]*\"/text=\"v$versionNumber\"/" "$PROJECT_DIR/$PROJECT_NAME/App/Base.lproj/LaunchScreen.storyboard"
但在 Xcode 11 中,项目的构建设置中有一个名为 Versioning
的新部分
并且CFBundleShortVersionString
自动更改为$(MARKETING_VERSION)
。 Xcode 自动处理,我不想手动将其更改为静态数字,让 Xcode 完成它的工作。
所以问题是我如何访问这个新的 MARKETING_VERSION
并使用 运行 脚本?
将它设置到我的 launchScreen 标签
您可以像使用任何其他项目变量一样使用它:
sourceFilePath="$PROJECT_DIR/$PROJECT_NAME/App/Base.lproj/LaunchScreen.storyboard"
versionNumber="$MARKETING_VERSION"
buildNumber="$CURRENT_PROJECT_VERSION"
sed -i .bak -e "/userLabel=\"APP_VERSION_LABEL\"/s/text=\"[^\"]*\"/text=\"v$versionNumber\"/" "$PROJECT_DIR/$PROJECT_NAME/App/Base.lproj/LaunchScreen.storyboard"
对于Node.js:有xcode package。使用示例:
const xcode = require('xcode');
const project = xcode.project('ios/PROJECT_NAME.xcodeproj/project.pbxproj').parse(() => {
const config = project.pbxXCBuildConfigurationSection();
const releaseScheme = Object.keys(config).find(key => config[key].name === 'Release');
const version = config[releaseScheme].buildSettings.MARKETING_VERSION;
});
之前我使用了 plist
包,但随着最近的 xCode 更改它变得过时了,因为我无法从 Info.plist
中提取 React Native 项目的版本。
我有类似的问题,通过显示 MARKETING_VERSION 本身使它起作用:
version="$MARKETING_VERSION"
version+=" ("
version+=`/usr/libexec/PlistBuddy -c "Print CFBundleVersion" $SRCROOT/MyApp/Info.plist`
version+=")"
/usr/libexec/PlistBuddy "$SRCROOT/MyApp/Settings.bundle/Root.plist" -c "set PreferenceSpecifiers:1:DefaultValue $version"
在互联网上找不到正确的答案,所以我开始挖掘。
版本号和内部版本号在 ./PROJECTNAME.xcodeproj/project.pbxproj
中显示为营销版本 (MV) 和当前项目版本 (CPV)。
我使用 sed 来获取数字。它找到 第一次出现 的 MV 或 CPV,删除除数字之外的所有内容,然后 returns 结果。为了让它工作,你需要做两件事:
- 导航到项目根文件夹
- 将 PROJECTNAME 更改为您的项目名称
命令:
version_number=`sed -n '/MARKETING_VERSION/{s/MARKETING_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' ./PROJECTNAME.xcodeproj/project.pbxproj`
build_number=`sed -n '/CURRENT_PROJECT_VERSION/{s/CURRENT_PROJECT_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' ./PROJECTNAME.xcodeproj/project.pbxproj`
结果:
注意:如果您的工作区中有更多具有不同版本和内部版本号的目标,这可能对您有用,也可能不适合您,因为它会在第一次出现时停止。那样的话,祝你好运:)
我正在为这种情况开发一个框架:
- 一个工作区
- 框架目标
- 具有 2 个外部脚本的聚合目标:
- 一个用于构建胖框架
- 其他准备发布框架
关键是 在 XCode11 中,聚合框架脚本没有为其他工作区目标运行获取环境变量,因此无法读取来自我的框架目标的 $MARKETING_VERSION。
所以对我有用的解决方案是 使用 PlistBuddy 指定框架目标构建的 Info.plist 结果 这样:
FAT_FRAMEWORK="${SRCROOT}/build/${FRAMEWORK_NAME}.framework"
BUILD_NUMBER=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${FAT_FRAMEWORK}/Info.plist")
VERSION_NUMBER=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${FAT_FRAMEWORK}/Info.plist")
如果你使用 Bitrise 那么下面的脚本将会拯救你:
正在提取 App Marketing 版本
envman add --key=APP_VERSION_NO --value=`sed -n '/MARKETING_VERSION/{s/MARKETING_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' ./${PATH_TO_YOUR_PROJECT_XCODEPROJ_FILE}/project.pbxproj`
正在提取应用内部版本号
仅当您使用 Apple Generic 版本控制系统时,才从 xcodeproj 文件中提取内部版本号,否则从 XCode 项目 info.plist 文件中提取内部版本号。
注意:以下脚本从 xcodeproj 文件中提取内部版本号。
envman add --key=APP_BUILD_NO --value=`sed -n '/CURRENT_PROJECT_VERSION/{s/CURRENT_PROJECT_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' ./${PATH_TO_YOUR_PROJECT_XCODEPROJ_FILE}/project.pbxproj`
打印到控制台:
envman run bash -c 'echo "App Version: $APP_VERSION_NO"'
envman run bash -c 'echo "App Build No: $APP_BUILD_NO"'
感谢@babac 的回答
Xcode 11/12
在项目的终端或bash脚本中您可以使用:
应用版本
xcodebuild -showBuildSettings | grep MARKETING_VERSION | tr -d 'MARKETING_VERSION =' // will be displayed 1.1.6
构建版本
xcodebuild -showBuildSettings | grep CURRENT_PROJECT_VERSION | tr -d 'CURRENT_PROJECT_VERSION =' // will be displayed 7
或者(不要忘记将 YouProjectName 更改为您的项目名称):
应用版本
cat YouProjectName.xcodeproj/project.pbxproj | grep -m1 'MARKETING_VERSION' | cut -d'=' -f2 | tr -d ';' | tr -d ' '
构建版本
cat YouProjectName.xcodeproj/project.pbxproj | grep -m1 'CURRENT_PROJECT_VERSION' | cut -d'=' -f2 | tr -d ';' | tr -d ' '
或较慢的方法(Thx Joshua Kaden):
应用版本
xcodebuild -project YouProjectName.xcodeproj -showBuildSettings | grep "MARKETING_VERSION" | sed 's/[ ]*MARKETING_VERSION = //'
构建版本
xcodebuild -project YouProjectName.xcodeproj -showBuildSettings | grep "CURRENT_PROJECT_VERSION" | sed 's/[ ]*CURRENT_PROJECT_VERSION = //'
如何将值保存到 CURRENT_PROJECT_VERSION?有没有人设法做到这一点?
我可以得到这样的值
buildNumber=$CURRENT_PROJECT_VERSION
但这不起作用:
CURRENT_PROJECT_VERSION="" or $CURRENT_PROJECT_VERSION=""
就我而言,我试图将其设置为“”
这一行也没有设置 CURRENT_PROJECT_VERSION 字段
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$appInfoPlist"
我在这里错过了针对多个目标和配置的解决方案:
xcodebuild -target <target> -configuration <configuaration> -showBuildSettings | grep -i 'MARKETING_VERSION' | sed 's/[ ]*MARKETING_VERSION = //'
- target:目标名称
- 配置:发布,调试
如果您的项目设置为使用 Apple 通用版本控制,那么您可以使用此命令:
agvtool what-marketing-version -terse1
有关如何设置 AGV 的更多信息,请参见 here。
目前投票最多的答案显示了如何通过 sed
和链中的其他工具提取价值。想通过 awk
.
提供一个(更简单的?)解决方案
只是为了提供一点上下文,下面一行显示了罪魁祸首行:
xcodebuild -project MyProj/MyProj.xcodeproj -showBuildSettings | awk '/MARKETING_VERSION/ { print }'
# output
MARKETING_VERSION = 0.0.1
默认的 awk 字段分隔符应该是 space,所以只需要提取第三个字段(MARKETING_VERSION 是第一个,等于符号是第二个):
xcodebuild -project MyProj/MyProj.xcodeproj -showBuildSettings | awk '/MARKETING_VERSION/ { print }'
# output
0.0.1
HTH
直到 Xcode 11,我使用了一个脚本来读取当前应用程序版本(对于 AppStore)并帮助我更改 LaunchScreen,因为我们无法使用swift 为此。
sourceFilePath="$PROJECT_DIR/$PROJECT_NAME/App/Base.lproj/LaunchScreen.storyboard"
versionNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$INFOPLIST_FILE")
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
sed -i .bak -e "/userLabel=\"APP_VERSION_LABEL\"/s/text=\"[^\"]*\"/text=\"v$versionNumber\"/" "$PROJECT_DIR/$PROJECT_NAME/App/Base.lproj/LaunchScreen.storyboard"
但在 Xcode 11 中,项目的构建设置中有一个名为 Versioning
的新部分并且CFBundleShortVersionString
自动更改为$(MARKETING_VERSION)
。 Xcode 自动处理,我不想手动将其更改为静态数字,让 Xcode 完成它的工作。
所以问题是我如何访问这个新的 MARKETING_VERSION
并使用 运行 脚本?
您可以像使用任何其他项目变量一样使用它:
sourceFilePath="$PROJECT_DIR/$PROJECT_NAME/App/Base.lproj/LaunchScreen.storyboard"
versionNumber="$MARKETING_VERSION"
buildNumber="$CURRENT_PROJECT_VERSION"
sed -i .bak -e "/userLabel=\"APP_VERSION_LABEL\"/s/text=\"[^\"]*\"/text=\"v$versionNumber\"/" "$PROJECT_DIR/$PROJECT_NAME/App/Base.lproj/LaunchScreen.storyboard"
对于Node.js:有xcode package。使用示例:
const xcode = require('xcode');
const project = xcode.project('ios/PROJECT_NAME.xcodeproj/project.pbxproj').parse(() => {
const config = project.pbxXCBuildConfigurationSection();
const releaseScheme = Object.keys(config).find(key => config[key].name === 'Release');
const version = config[releaseScheme].buildSettings.MARKETING_VERSION;
});
之前我使用了 plist
包,但随着最近的 xCode 更改它变得过时了,因为我无法从 Info.plist
中提取 React Native 项目的版本。
我有类似的问题,通过显示 MARKETING_VERSION 本身使它起作用:
version="$MARKETING_VERSION"
version+=" ("
version+=`/usr/libexec/PlistBuddy -c "Print CFBundleVersion" $SRCROOT/MyApp/Info.plist`
version+=")"
/usr/libexec/PlistBuddy "$SRCROOT/MyApp/Settings.bundle/Root.plist" -c "set PreferenceSpecifiers:1:DefaultValue $version"
在互联网上找不到正确的答案,所以我开始挖掘。
版本号和内部版本号在 ./PROJECTNAME.xcodeproj/project.pbxproj
中显示为营销版本 (MV) 和当前项目版本 (CPV)。
我使用 sed 来获取数字。它找到 第一次出现 的 MV 或 CPV,删除除数字之外的所有内容,然后 returns 结果。为了让它工作,你需要做两件事:
- 导航到项目根文件夹
- 将 PROJECTNAME 更改为您的项目名称
命令:
version_number=`sed -n '/MARKETING_VERSION/{s/MARKETING_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' ./PROJECTNAME.xcodeproj/project.pbxproj`
build_number=`sed -n '/CURRENT_PROJECT_VERSION/{s/CURRENT_PROJECT_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' ./PROJECTNAME.xcodeproj/project.pbxproj`
结果:
注意:如果您的工作区中有更多具有不同版本和内部版本号的目标,这可能对您有用,也可能不适合您,因为它会在第一次出现时停止。那样的话,祝你好运:)
我正在为这种情况开发一个框架:
- 一个工作区
- 框架目标
- 具有 2 个外部脚本的聚合目标:
- 一个用于构建胖框架
- 其他准备发布框架
关键是 在 XCode11 中,聚合框架脚本没有为其他工作区目标运行获取环境变量,因此无法读取来自我的框架目标的 $MARKETING_VERSION。
所以对我有用的解决方案是 使用 PlistBuddy 指定框架目标构建的 Info.plist 结果 这样:
FAT_FRAMEWORK="${SRCROOT}/build/${FRAMEWORK_NAME}.framework"
BUILD_NUMBER=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${FAT_FRAMEWORK}/Info.plist")
VERSION_NUMBER=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${FAT_FRAMEWORK}/Info.plist")
如果你使用 Bitrise 那么下面的脚本将会拯救你:
正在提取 App Marketing 版本
envman add --key=APP_VERSION_NO --value=`sed -n '/MARKETING_VERSION/{s/MARKETING_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' ./${PATH_TO_YOUR_PROJECT_XCODEPROJ_FILE}/project.pbxproj`
正在提取应用内部版本号
仅当您使用 Apple Generic 版本控制系统时,才从 xcodeproj 文件中提取内部版本号,否则从 XCode 项目 info.plist 文件中提取内部版本号。
注意:以下脚本从 xcodeproj 文件中提取内部版本号。
envman add --key=APP_BUILD_NO --value=`sed -n '/CURRENT_PROJECT_VERSION/{s/CURRENT_PROJECT_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' ./${PATH_TO_YOUR_PROJECT_XCODEPROJ_FILE}/project.pbxproj`
打印到控制台:
envman run bash -c 'echo "App Version: $APP_VERSION_NO"'
envman run bash -c 'echo "App Build No: $APP_BUILD_NO"'
感谢@babac 的回答
Xcode 11/12
在项目的终端或bash脚本中您可以使用:
应用版本
xcodebuild -showBuildSettings | grep MARKETING_VERSION | tr -d 'MARKETING_VERSION =' // will be displayed 1.1.6
构建版本
xcodebuild -showBuildSettings | grep CURRENT_PROJECT_VERSION | tr -d 'CURRENT_PROJECT_VERSION =' // will be displayed 7
或者(不要忘记将 YouProjectName 更改为您的项目名称):
应用版本
cat YouProjectName.xcodeproj/project.pbxproj | grep -m1 'MARKETING_VERSION' | cut -d'=' -f2 | tr -d ';' | tr -d ' '
构建版本
cat YouProjectName.xcodeproj/project.pbxproj | grep -m1 'CURRENT_PROJECT_VERSION' | cut -d'=' -f2 | tr -d ';' | tr -d ' '
或较慢的方法(Thx Joshua Kaden):
应用版本
xcodebuild -project YouProjectName.xcodeproj -showBuildSettings | grep "MARKETING_VERSION" | sed 's/[ ]*MARKETING_VERSION = //'
构建版本
xcodebuild -project YouProjectName.xcodeproj -showBuildSettings | grep "CURRENT_PROJECT_VERSION" | sed 's/[ ]*CURRENT_PROJECT_VERSION = //'
如何将值保存到 CURRENT_PROJECT_VERSION?有没有人设法做到这一点?
我可以得到这样的值
buildNumber=$CURRENT_PROJECT_VERSION
但这不起作用:
CURRENT_PROJECT_VERSION="" or $CURRENT_PROJECT_VERSION=""
就我而言,我试图将其设置为“”
这一行也没有设置 CURRENT_PROJECT_VERSION 字段
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$appInfoPlist"
我在这里错过了针对多个目标和配置的解决方案:
xcodebuild -target <target> -configuration <configuaration> -showBuildSettings | grep -i 'MARKETING_VERSION' | sed 's/[ ]*MARKETING_VERSION = //'
- target:目标名称
- 配置:发布,调试
如果您的项目设置为使用 Apple 通用版本控制,那么您可以使用此命令:
agvtool what-marketing-version -terse1
有关如何设置 AGV 的更多信息,请参见 here。
目前投票最多的答案显示了如何通过 sed
和链中的其他工具提取价值。想通过 awk
.
只是为了提供一点上下文,下面一行显示了罪魁祸首行:
xcodebuild -project MyProj/MyProj.xcodeproj -showBuildSettings | awk '/MARKETING_VERSION/ { print }'
# output
MARKETING_VERSION = 0.0.1
默认的 awk 字段分隔符应该是 space,所以只需要提取第三个字段(MARKETING_VERSION 是第一个,等于符号是第二个):
xcodebuild -project MyProj/MyProj.xcodeproj -showBuildSettings | awk '/MARKETING_VERSION/ { print }'
# output
0.0.1
HTH