Xcode — 构建版本号
This article is extracted from the chat log with AI. Please identify it with caution.

DeepSeek #

在 Xcode Cloud 中获取构建版本号并集成到你的 App 中,可以通过以下步骤实现:


方法 1:通过 Xcode Cloud 环境变量直接获取 #

Xcode Cloud 提供了一系列预定义的环境变量,其中 CI_BUILD_NUMBER 是每次构建的递增编号。你需要通过以下步骤将它注入到你的 App 中:

步骤 1:在 Xcode 项目中配置版本号 #

  1. 打开你的 Xcode 项目,进入 TargetBuild Settings
  2. 搜索 Current Project Version(或 CURRENT_PROJECT_VERSION)。
  3. 将值设置为 $(CI_BUILD_NUMBER),这样 Xcode Cloud 构建时会自动替换为实际值。
    • 注意:为了本地开发时不会报错,可以设置默认值:$(CI_BUILD_NUMBER:0)(当环境变量不存在时,回退到 0)。

步骤 2:在 Info.plist 中引用版本号 #

  1. 打开 Info.plist,找到 CFBundleVersion(或创建它)。
  2. 将值设置为 $(CURRENT_PROJECT_VERSION),这样会动态读取步骤 1 中配置的值。

方法 2:通过自定义脚本注入到代码中 #

如果你需要在代码中直接访问构建号(例如显示在 UI 中),可以通过脚本将环境变量写入代码文件:

步骤 1:添加 Pre-action 脚本 #

  1. 在 Xcode 项目中,进入 TargetBuild Phases
  2. 点击 + 添加一个 New Run Script Phase
  3. 粘贴以下脚本:
# 将构建号写入 Swift 文件
BUILD_NUMBER=${CI_BUILD_NUMBER:-0}
echo "// Generated by script\nstruct BuildInfo {\n static let number = \"$BUILD_NUMBER\"\n}" > "${SRCROOT}/BuildInfo.swift"

这会生成一个 BuildInfo.swift 文件,内容类似:

struct BuildInfo {
    static let number = "123" // Xcode Cloud 的构建号
}

步骤 2:在代码中使用构建号 #

// 在需要的地方调用
let buildNumber = BuildInfo.number
label.text = "Build: \(buildNumber)"

方法 3:通过 Info.plist 直接读取 #

如果你只需要显示标准版本号,可以直接读取 Bundle 信息:

if let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
    print("Build Number: \(buildNumber)")
}

验证本地和 Xcode Cloud 行为 #

  • 本地开发:如果未设置 CI_BUILD_NUMBER,脚本会回退到默认值(例如 0)。
  • Xcode Cloud:构建时自动注入实际值(如 123)。

补充说明 #

  • 环境变量清单:Xcode Cloud 提供的其他环境变量(如 CI_COMMITCI_BRANCH)可在 Apple 官方文档 查看。
  • 自动版本管理:如果你使用 agvtool,可以结合 CI_BUILD_NUMBER 自动递增版本号:
agvtool new-version -all $CI_BUILD_NUMBER

通过上述任一方法,你都可以在 App 中显示 Xcode Cloud 的构建版本号。推荐使用 方法 2,因为它灵活且能直接在代码中访问动态值。

ChatGPT #

概要 #

在 Xcode Cloud 中,每次构建时都会自动注入一个名为 CI_BUILD_NUMBER(或等效 XCODE_CLOUD_BUILD_NUMBER)的环境变量,其值即为该次构建的 build number。要将此值放入 App 中,通常有两步:

  1. 在构建脚本中,将 CI_BUILD_NUMBER 写入项目的 Info.plist 对应的 CFBundleVersion 字段;

  2. 在运行时代码中,从 Bundle.main.infoDictionary 读取 CFBundleVersion(以及可选的 CFBundleShortVersionString)并显示在 UI 内。

下面详细介绍这两步的实现方法。


1. Xcode Cloud 提供的环境变量 #

  • CI_BUILD_NUMBER
    Xcode Cloud 会将每次构建的整数编号置入此环境变量,自动递增。
    (Stack Overflow)

  • (别名)XCODE_CLOUD_BUILD_NUMBER
    有些文档和社区示例中也会用此名字,但二者等效。
    (Stack Overflow)


2. 在构建前脚本中写入 Info.plist #

  1. 创建脚本目录
    在 Xcode 项目根目录下新建一个名为 ci_scripts 的文件夹,添加到 Project Navigator。

  2. 添加预构建脚本
    ci_scripts 内新建文件 ci_pre_xcodebuild.sh,并确保执行权限:

    chmod +x ci_scripts/ci_pre_xcodebuild.sh
    
  3. 脚本内容示例
    ci_pre_xcodebuild.sh 中使用 PlistBuddyplutil 将环境变量写入 Info.plist:

    #!/bin/sh
    echo "Setting CFBundleVersion to Xcode Cloud build number..."
    
    # 进入项目目录(根据实际路径调整)
    cd "$CI_PRIMARY_REPOSITORY_PATH"
    
    # 使用 PlistBuddy
    /usr/libexec/PlistBuddy \
      -c "Set :CFBundleVersion $CI_BUILD_NUMBER" \
      "${PROJECT_DIR}/${INFOPLIST_FILE}"
    
    # 或使用 plutil:
    # plutil -replace CFBundleVersion -string "$CI_BUILD_NUMBER" \
    #   "${PROJECT_DIR}/${INFOPLIST_FILE}"
    
    echo "Done. CFBundleVersion is now $CI_BUILD_NUMBER."
    

    这样,后续的 Xcode 构建流程就会使用这个新的 CFBundleVersion 值。
    (Stack Overflow)


3. 在 Swift 中读取并显示版本号 #

在应用运行时,可通过 Bundle 读取 Info.plist 中的字段:

if let info = Bundle.main.infoDictionary {
    let shortVersion = info["CFBundleShortVersionString"] as? String ?? "0"
    let buildNumber  = info["CFBundleVersion"] as? String ?? "0"
    let versionText  = "v\(shortVersion) (\(buildNumber))"
    // 例如显示在界面标签上:
    versionLabel.text = versionText
}
  • CFBundleShortVersionString —— 用户可见的“版本号”,如 1.2.3

  • CFBundleVersion —— 内部构建号,此处即来自 CI_BUILD_NUMBER
    (Paulius Gudonis)


4. 小结 #

  • 核心变量CI_BUILD_NUMBERXCODE_CLOUD_BUILD_NUMBER(Xcode Cloud 自动提供)

  • 脚本注入:在 ci_pre_xcodebuild.sh 中用 PlistBuddyplutil 写入 Info.plist

  • 运行读取Bundle.main.infoDictionary 获取 CFBundleVersion

这样即可在每次 Xcode Cloud 构建后,将自动递增的构建版本号嵌入 App,并在运行时展示给用户或用于埋点等用途。

Version 版本号 #

概要 #

Xcode Cloud 本身只提供内置的 CI_BUILD_NUMBER(或同义的 XCODE_CLOUD_BUILD_NUMBER)环境变量用于构建号,但并不自动注入“版本号”(即 Info.plist 中的 CFBundleShortVersionString)(Apple Developer)。要在 CI 构建中获取和控制版本号,常见做法是:

  1. 在 Xcode 项目中预先设置好“Version”(对应 CFBundleShortVersionString)(Apple Developer);
  2. 在 Xcode Cloud Workflow 的 Environment 配置中添加自定义环境变量(如 APP_VERSION)(Apple Developer);
  3. 在自定义构建脚本(ci_pre_xcodebuild.sh)中,将该环境变量写入 Info.plist 或使用 agvtool 更新营销版本;
  4. 在运行时代码中,通过 Bundle.main.infoDictionary 读取并显示版本号和构建号(Stack Overflow)。

1. 预先在 Xcode 项目中设置版本号 #

  • 打开 Xcode,选中 Target → GeneralVersion,填写符合三段式语义版本(如 1.2.3)的字符串,对应 Info.plist 中的 CFBundleShortVersionString (Apple Developer)。

  • 同时,“Build” 字段对应 CFBundleVersion,但 Xcode Cloud 会覆盖它为 CI_BUILD_NUMBER,因此一般无需手动填写或可留空由脚本设置(Apple Developer)。


2. 在 Xcode Cloud Workflow 中添加自定义环境变量 #

  1. Xcode Cloud 的工作流(Workflow)编辑界面中,导航至 EnvironmentCustom environment variables,点击“+”添加一行,例如:

    Key: APP_VERSION
    Value: 1.2.3
    Secret: Off

    这样 APP_VERSION 就会作为环境变量注入到构建容器中(Apple Developer)。

  2. 如果希望根据 Git 标签或其他策略动态管理版本号,也可在此处使用脚本或环境变量引用,如 $CI_COMMIT_TAG(触发时若基于 Tag,则可取到 v1.2.3)(Apple Developer)。


3. 在构建脚本中写入版本号 #

创建或修改 ci_scripts/ci_pre_xcodebuild.sh,将 APP_VERSION 注入到 Info.plist:

方法 A:使用 plutil #

#!/bin/sh

echo "Setting CFBundleShortVersionString to $APP_VERSION"
/usr/libexec/PlistBuddy \
  -c "Set :CFBundleShortVersionString $APP_VERSION" \
  "${PROJECT_DIR}/${INFOPLIST_FILE}"
echo "Done."

该脚本会在 Xcode 执行 xcodebuild 前运行,将 Info.plist 中的 CFBundleShortVersionString 更新为环境变量 APP_VERSION 的值(Apple 开发者论坛)。

方法 B:使用 agvtool #

#!/bin/sh

echo "Updating marketing version via agvtool to $APP_VERSION"
cd "$CI_PRIMARY_REPOSITORY_PATH"
xcrun agvtool new-marketing-version "$APP_VERSION"
echo "Done."

agvtool new-marketing-version 会修改项目设置和 Info.plist 中的 CFBundleShortVersionString,前提是已在 Xcode 中启用 Apple Generic Versioning(项目 Build Settings 中设置 CURRENT_PROJECT_VERSION 和关闭自动生成 Info.plist)(Apple Developer)。


4. 在运行时读取并显示版本号 #

在 Swift 代码中,通过 Bundle.main.infoDictionary 获取并组合版本号与构建号:

if let info = Bundle.main.infoDictionary {
    let shortVersion = info["CFBundleShortVersionString"] as? String ?? "0"
    let buildNumber  = info["CFBundleVersion"] as? String ?? "0"
    let versionText  = "v\(shortVersion) (\(buildNumber))"
    versionLabel.text = versionText
}
  • CFBundleShortVersionString —— 对应用户可见的“版本号”(Stack Overflow)

  • CFBundleVersion —— 对应内部“构建号”,在 Xcode Cloud 下即注入的 CI_BUILD_NUMBER(Apple Developer)


5. 小结 #

  • 版本号(Marketing Version)由 CFBundleShortVersionString 决定,需在项目中预设或脚本注入(plutil/agvtool)。

  • 构建号(Build Number)由 Xcode Cloud 环境变量 CI_BUILD_NUMBER(或 XCODE_CLOUD_BUILD_NUMBER)提供。

  • 通过在 Workflow 添加自定义变量(如 APP_VERSION)、编写 ci_pre_xcodebuild.sh 脚本实现动态注入,并在运行时代码中读取 Info.plist 即可将版本号和构建号嵌入 App。

  • 建议保持版本号和构建号并行管理,以便在 App Store Connect 和内部测试中清晰区分每次发布(Stack Overflow)。

这样,你就可以在 Xcode Cloud 的每次构建中,既获取到自动递增的构建号,又灵活控制和读取版本号,将两者统一展示或用于埋点、日志等场景。

本文共 3085 字,创建于 May 6, 2025
相关标签: Xcode, ByAI, DeepSeek, ChatGPT