如何使用脚本在Xcode 11中读取当前应用程序版本

51

在 Xcode 11 之前,我使用一个脚本来读取当前应用程序版本(用于 AppStore),并帮助我更改启动屏幕,因为我们不能使用 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 的新部分。

enter image description here

CFBundleShortVersionString 自动更改为 $(MARKETING_VERSION)。 Xcode会自动处理这个问题,我不想手动更改为静态数字,让Xcode自己完成工作。

11

因此问题是如何使用运行脚本访问这个新的MARKETING_VERSION并将其设置为我的启动屏幕标签?

12个回答

49

Xcode 11-14

终端项目中的bash脚本中,您可以使用以下命令:

应用版本

xcodebuild -showBuildSettings | grep MARKETING_VERSION | tr -d 'MARKETING_VERSION =' // 将显示1.1.6

构建版本

xcodebuild -showBuildSettings | grep CURRENT_PROJECT_VERSION | tr -d 'CURRENT_PROJECT_VERSION =' // 将显示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 ' '

或者较慢的方法(感谢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 = //'


1
如果您有多个构建方案需要获取其版本号,则可以使用此方法。只需在xcodebuild命令中传递 --scheme {SCHEME} 即可。 - SeanRobinson159
2
@SeanRobinson159 应该使用 -scheme {SCHEME},同时与 -workspace {name}.xcodeworkspace 一起工作。 - Raptor
“cat” 工作得很好!不错! - Praveenkumar

20

在互联网上找不到正确的答案,所以我开始深入挖掘。

版本和构建号显示在./PROJECTNAME.xcodeproj/project.pbxproj中作为营销版本(MV)和当前项目版本(CPV)。

版本号

构建号

我使用 sed 来获取数字。它查找MV或CPV的第一个出现,除数字外删除所有内容,并返回结果。为了使其工作,您需要执行两个操作:

  • 导航到项目根文件夹
  • 将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`

结果:

版本和构建号

注意:如果您的工作区有多个目标,版本和构建号不同,这可能适用或不适用于您,因为它会在第一次出现时停止。在那种情况下,祝你好运:)


1
不错。对我来说可行。 - VaporwareWolf
4
你应该使用 xcodebuild -showBuildSettings 命令来查看构建设置,而不是直接读取项目文件。 - Cy-4AH
4
xcodebuild -project ThreeOneOne.xcodeproj -showBuildSettings | grep "MARKETING_VERSION" | sed 's/[ ]*MARKETING_VERSION = //' - Joshua Kaden
尝试在三个项目上使用-showBuildSettings功能,但未能获取MARKETING_VERSION和CURRENT_PROJECT_VERSION。如果您可以获取它,请点赞并继续使用 :) - Babac
@Babac 希望你已经解决了这个问题。你无法获取 MARKETING_VERSION 的原因是你正在工作区而不是项目中(你手头有三个项目的提示)。要获取版本,你可以发出以下命令:xcodebuild -workspace YourName.xcodeworkspace -scheme YourSchemeName -showBuildSettings | grep "MARKETING_VERSION" - Raptor
任何关于如何获取第一个出现的数字而不是"$(inherited)"的想法? - Tommy Sadiq Hinrichsen

19
你可以像使用其他项目变量一样使用它:
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"

4
这对我来说不起作用,或者我漏掉了某些东西。 - Craig Fisher
1
有没有办法在终端中打印出$MARKETING_VERSION的当前值? - Hans Bondoka
2
@HansBondoka echo "营销版本是:$MARKETING_VERSION" - Nicholas

6

我希望你能提供一个适用于多个目标和配置的解决方案:

xcodebuild -target <target> -configuration <configuaration> -showBuildSettings  | grep -i 'MARKETING_VERSION' | sed 's/[ ]*MARKETING_VERSION = //'
  • 目标: 目标的名称
  • 配置: 发布版,调试版

谢谢!那正是我所需要的。 - Martin

3
如果您使用Bitrise,则以下脚本将为您节省时间:
提取应用程序营销版本
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通用版本控制系统时,才从xcodeproj文件中提取Build Number,否则从XCode项目info.plist文件中提取Build Number。
注意:以下脚本从xcodeproj文件中提取Build Number。
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的回答。

2
到目前为止,大多数得票最高的答案都展示了如何通过sed和进一步的工具在链中提取值。我想提供一个(更简单?)的解决方案,只需要使用awk即可。

只是为了给出一点背景,以下一行代码显示了罪魁祸首的行:

xcodebuild -project MyProj/MyProj.xcodeproj -showBuildSettings | awk '/MARKETING_VERSION/ { print }'

# output
    MARKETING_VERSION = 0.0.1

默认awk字段分隔符应为空格,因此只需要提取第三个字段(MARKETING_VERSION在第一位,等号在第二位):

xcodebuild -project MyProj/MyProj.xcodeproj -showBuildSettings | awk '/MARKETING_VERSION/ { print $3 }'

# output
0.0.1

HTH


为什么我会收到一个错误,说DVTAssertions: Warning in /Library/Caches/com.apple.xbs/Sources/DVTiOSFrameworks/DVTiOSFrameworks-19450/DTDeviceKitBase/DTDKRemoteDeviceData.m:373 - user2027712
嗨@user2027712。根据提供的信息,我一无所知。我建议您为此打开一个专门的问题,并提供所有必要的上下文、更多信息等。更好的方法是,如果您还没有这样做,请尝试在网络上搜索该错误消息。它似乎不是来自命令行的错误,这是本答案的主要话题。我猜您的Xcode构建中肯定有其他问题。 - superjos

1
如果您的项目使用了苹果通用版本控制,则可以使用以下命令:

Apple Generic Versioning

agvtool what-marketing-version -terse1

您可以在此处找到有关如何设置AGV的更多信息。


如果版本是在Info.plist文件中设置而不是在构建设置中设置,那么这实际上是一种更清晰的方式。谢谢! - iltercengiz

1

有人成功将值保存到CURRENT_PROJECT_VERSION吗?

我可以像这样获取该值:

buildNumber=$CURRENT_PROJECT_VERSION

but this doesn't work:

CURRENT_PROJECT_VERSION=""    or   $CURRENT_PROJECT_VERSION=""

在我的情况下,我正在尝试将其设置为""。
这行代码也没有设置CURRENT_PROJECT_VERSION字段。
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$appInfoPlist"

0
你可以使用 jq,因为 xcodebuild-json 选项。
❯ xcodebuild -showBuildSettings -json 2>/dev/null | jq '.[0].buildSettings.MARKETING_VERSION'
"0.1.0"

❯ xcodebuild -showBuildSettings -json 2>/dev/null | jq '.[0].buildSettings.CURRENT_PROJECT_VERSION'
"1"

jq -r 打印原始值:

❯ xcodebuild -showBuildSettings -json 2>/dev/null | jq -r '.[0].buildSettings.MARKETING_VERSION'
0.1.0

❯ xcodebuild -showBuildSettings -json 2>/dev/null | jq -r '.[0].buildSettings.CURRENT_PROJECT_VERSION'
1

jq是什么?我的Mac上没有叫做jq的东西。 - HangarRash
这是一个众所周知的JSON处理开源软件。jq不会默认安装。https://github.com/jqlang/jq/ 您可以使用任何能够处理JSON的脚本语言,或者您可以通过Homebrew安装jq。 - mtgto
在你的回答中加入这些信息会很有帮助。 - HangarRash

0

我正在开发一个框架,其场景如下:

  • 一个工作区
  • 一个框架目标
  • 一个包含两个外部脚本的聚合目标:
    • 一个用于构建fat框架
    • 另一个用于准备发布框架

关键在于,在XCode 11中,聚合框架脚本不会运行其他工作区目标的环境变量,因此无法从我的框架目标中读取$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")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接