Xcode 中的 Scheme 是一种配置,它决定了如何为 iOS、macOS、watchOS 或 tvOS 构建、测试、性能分析和归档应用程序。每个 Scheme 都包含一组操作(Build、Run、Test、Profile、Analyze、Archive),并带有各自的参数、启动参数和环境变量。根据 Apple Developer Documentation, 2025,Scheme 是 Xcode 中管理构建配置的主要工具,取代了手动切换参数。在首次打开项目时,Xcode 会自动为每个 target 创建一个方案。
要点
Xcode 中的 Scheme 是一个 XML 文件(扩展名为 .xcscheme),它描述了构建和分析应用程序的操作序列及其参数。每个 Scheme 都绑定到一个或多个 target,并决定每个操作使用哪种配置(Debug、Release、AdHoc)执行。Scheme 相当于 Android 中的 Build Variant,但结构更灵活:一个方案可以针对不同操作包含不同 target。
Xcode 在首次打开项目时会自动为每个 target 创建一个方案。方案的默认名称与 target 名称一致。如果项目中有测试 target,Xcode 会自动将其添加到主 target 方案的 Test 操作中。对于包含多个 target 的项目(主应用 + watchOS + extension),Xcode 会为每个 target 创建单独方案,但也可以创建一个一次构建所有 target 的方案。
方案存储在 xcshareddata/xcschemes/ 目录(用于 shared)或 xcuserdata/<user>/xcschemes/ 目录(用于 private)中。Shared 方案会进入 Git 并由整个团队使用。Private 方案存储在本地,不会同步。.xcscheme 文件采用 XML 格式,根元素为 <Scheme>。内部包含每个操作的块:BuildAction、TestAction、LaunchAction、ProfileAction、AnalyzeAction、ArchiveAction。
.xcscheme 是一个 XML 文件,可以手动编辑或通过 Xcode 编辑。主要元素:<BuildAction>(要构建的 target 列表)、<TestAction>(对测试 target 的引用)、<LaunchAction>(启动配置)、<ProfileAction>、<AnalyzeAction>、<ArchiveAction>。每个块都包含 buildConfiguration 属性,该属性决定该操作使用哪种配置(Debug/Release)。
Scheme 由六个操作组成,每个操作都可以独立配置。Build Action 决定构建哪些 target 以及构建顺序。Run Action — 如何启动应用程序:使用哪些启动参数、环境变量以及哪种配置。Test Action — 执行哪些测试以及启用哪些 code coverage 选项。Profile Action — 使用 Instruments 工具进行性能分析。Analyze Action — 使用 Clang Static Analyzer 进行静态代码分析。Archive Action — 为发布到 App Store 或 AdHoc 分发而构建。
可以为每个操作设置单独的 build configuration。通常 Run 和 Test 使用 Debug,Archive 使用 Release。Build configuration 决定编译器标志、优化和调试信息的集合。Xcode 提供两种标准配置:Debug(无优化,带调试符号)和 Release(带优化,无调试信息)。开发人员可以通过 project.xcconfig 添加自定义配置。
Archive 操作尤其重要 — 它创建 .xcarchive,随后导出为 .ipa 用于 App Store 或 AdHoc。Archive Action 默认使用 Release 配置,但可以切换到 AdHoc 或 Distribution。在 Archive Action 中还可以使用 revealArchiveInOrganizer 标志 — 归档完成后,Xcode 会打开 Organiser 以对归档执行进一步操作。
<!-- iOS 应用的 .xcscheme 示例 -->
<Scheme
LastUpgradeVersion = "1500"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ABCD1234"
BuildableName = "MyApp.app"
BlueprintName = "MyApp"
ReferencedContainer = "container:MyApp.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
enableAddressSanitizer = "YES">
</LaunchAction>
</Scheme>
通过 Xcode 菜单创建新方案:Product → Scheme → New Scheme 或点击 Scheme 面板(Run 按钮旁边)中的 “+” 按钮。创建时选择要为哪个 target 创建方案。如果方案被选为 “duplicate”,Xcode 会自动复制现有方案的设置。新方案默认保存为 private — 要发布给团队,需要在 Manage Schemes 中启用 Shared。
Edit Scheme 窗口(Product → Scheme → Edit Scheme)包含六个选项卡,与操作数量对应。在每个选项卡上都可以更改 build configuration、启动参数、环境变量和诊断标志。在 Run 选项卡中有以下选项:executable(运行哪个二进制文件)、wait for executable to be launched(用于调试启动的进程)、debugger(LLDB 或 None)、launch arguments、environment variables,以及高级选项(Address Sanitizer、Thread Sanitizer、Main Thread Checker、Memory Management)。
用于诊断:Address Sanitizer(ASan)— 检测数组越界、use-after-free 以及 C/C++/ObjC 代码中的其他内存错误。Thread Sanitizer(TSan)— 检测多线程代码中的数据竞争(data races)。Undefined Behavior Sanitizer(UBSan)— 揭示未定义行为,例如有符号 int 溢出。这些选项位于 Edit Scheme → Run → Diagnostics,仅适用于 Debug 构建。启用所有消毒器可能会使启动变慢 2-3 倍,因此建议有选择地启用它们。
典型做法 — 为每个环境创建单独方案:Dev、Staging、Production。每个方案使用相同的 Build Configuration(Dev 用 Debug,Production 用 Release),但使用不同的启动参数:Dev 使用 -FIRAnalyticsDebugEnabled、-com.apple.CoreData.SQLDebug 1,Production 不使用这些参数。启动参数会传入 UserDefaults(ProcessInfo.processInfo.arguments),并在应用程序启动时可读取。这样可以在不修改代码的情况下切换服务器 URL、日志级别和功能。
Shared 方案存储在 <project>.xcworkspace/xcshareddata/xcschemes/ 或 <project>.xcodeproj/xcshareddata/xcschemes/ 目录中,并进入 Git 仓库。团队的所有开发人员都能在 Xcode 中看到这些方案。Shared 方案是在团队中分发方案的唯一方式。如果开发人员创建了重要方案(例如 “Staging Archive”)但没有标记为 Shared,团队其他成员将看不到它,从而导致混乱:每个人都用自己的设置创建自己的方案。
Private 方案存储在 xcuserdata/<user>/xcschemes/ 目录中,不会进入 Git。它们适合个人配置:例如,为特定开发人员启用所有消毒器的方案。Private 方案不应包含项目构建所依赖的关键设置 — 如果开发人员离开项目,他的 private 方案会丢失。建议:将在 CI/CD 中以及至少两名开发人员使用的所有方案设为 Shared。
通过 Manage Schemes(Product → Scheme → Manage Schemes)管理方案。窗口中显示项目的所有方案、其状态(Shared/Private)以及用于添加/删除的 +/— 按钮。Shared 复选框切换方案对团队的可见性。发生 Git 冲突时(两名开发人员对 .xcscheme 的更改),需要谨慎解决合并 — XML 文件可能包含不同的 target 标识符。建议将 .xcscheme 添加到合并时锁定的文件中(git lfs 或 .gitattributes)。
Scheme 中的 Arguments 是在启动时传递给应用程序的字符串(ProcessInfo.processInfo.arguments)以及环境变量(ProcessInfo.processInfo.environment)。参数用于标志:-AppleLanguages (ru)、-AppleLocale ru_RU 用于模拟俄语区域设置,或 -FIRDebugEnabled 用于启用 Firebase 调试。环境变量用于配置:API_BASE_URL=http://localhost:3000、LOG_LEVEL=debug。
要在不同环境中管理功能(feature flags),使用 Arguments + Build Configuration 的组合。在 Dev 方案中设置参数 -FeatureFlagNewOnboarding YES,在 Production 中设置 -FeatureFlagNewOnboarding NO(或没有该参数)。在代码中检查:UserDefaults.standard.bool(forKey: “FeatureFlagNewOnboarding”)。这种方法允许在不修改代码、不提交生产值的情况下在 staging 上逐步启用功能。
重要:Scheme 的参数和环境变量会覆盖 Info.plist 中的值。如果 Info.plist 中指定了 API_URL,而 Scheme 中为 Run Action 指定了 API_URL=http://localhost,则从 Xcode 启动时将使用 Scheme 中的值。从设备启动(而非从 Xcode)时 — 使用 Info.plist 中的值。这便于本地开发,但要记住,Scheme 变量不会进入构建 — 它们仅在通过 Xcode 启动时生效。
import Foundation
struct AppEnvironment {
var apiBaseURL: String {
ProcessInfo.processInfo.environment["API_BASE_URL"]
?? Bundle.main.object(forInfoDictionaryKey: "API_BASE_URL") as? String
?? "https://api.production.com"
}
var isDebugMode: Bool {
ProcessInfo.processInfo.arguments.contains("-DebugModeEnabled")
}
var isNewOnboardingEnabled: Bool {
UserDefaults.standard.bool(forKey: "FeatureFlagNewOnboarding")
}
}
// 启动时使用
let env = AppEnvironment()
NetworkConfig.shared.configure(baseURL: env.apiBaseURL)
在 CI/CD(GitHub Actions、Jenkins、GitLab CI)中,Scheme 用作 xcodebuild 命令的主要参数。示例:xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Release -sdk iphoneos archive。-scheme 标志指定使用哪个方案。xcodebuild 从 .xcscheme 文件中读取所有设置,包括 build configuration、target 和构建顺序。这保证了 CI/CD 使用与本地 IDE 相同的参数构建应用程序。
对于 CI/CD,Shared 方案至关重要。如果方案不是 Shared,xcodebuild 将无法在仓库中找到它,构建将失败并报错 “Scheme not found”。规则:在配置 CI/CD 之前,确保所有使用的方案都标记为 Shared。第二条规则:在 CI/CD 中不要使用默认方案(Xcode 自动选择第一个方案)— 始终通过 -scheme 标志显式传递方案名称。
要并行构建多个方案(例如,应用和 watchOS 扩展),可以顺序或并行运行 xcodebuild。现代 CI 系统通过矩阵支持并行构建不同方案:一个 job 构建 iOS 应用,另一个构建 watchOS 扩展。在两个并行 agent 下,这可将总构建时间从 15 分钟缩短到 8 分钟。最后,使用 xcodebuild -exportArchive 将产物合并为一个 .xcarchive。
#!/bin/bash — 使用 xcodebuild 进行 CI/CD 构建
# 1. 清理并构建
xcodebuild clean archive \
-workspace "MyApp.xcworkspace" \
-scheme "MyApp Production" \
-configuration Release \
-sdk iphoneos \
-archivePath "build/MyApp.xcarchive" \
CODE_SIGN_STYLE="Manual" \
PROVISIONING_PROFILE_SPECIFIER="match AppStore"
# 2. 导出为 IPA
xcodebuild -exportArchive \
-archivePath "build/MyApp.xcarchive" \
-exportPath "build/ipa" \
-exportOptionsPlist "ExportOptions.plist"
常见问题
通常 2-3 个方案就足够了:Development(Debug)、Staging(带测试服务器参数)和 Production(Release)。对于模块化库 — 一个带测试设置的方案。不要创建过多方案 — 每个新方案都需要维护。
Build Configuration(Debug/Release)— 是在 .xcconfig 中定义的编译器标志集合。Scheme — 是一组操作,每个操作都引用一个 Build Configuration。方案说 “启动时使用 Debug”,配置定义 “Debug 意味着无优化、带符号”。
参数进入 ProcessInfo.processInfo.arguments 和 UserDefaults(如果参数以短横线开头)。环境变量进入 ProcessInfo.processInfo.environment。在代码中:对于 -FeatureFlag YES 形式的参数,使用 UserDefaults.standard.bool(forKey: “FeatureFlag”)。
可以,在 Build Action 中可以添加多个 target。例如,“App + Watch + Widget” 方案将顺序构建所有三个 target(如果 parallelizeBuildables=NO)或并行构建(YES)。归档应用只需主 target — 其余 target 作为依赖构建。
Swift Package Manager 不能替代方案 — 方案仍然决定用什么 配置 构建 SPM 依赖、运行哪些测试以及如何归档。SPM 包可以有自己方案,在添加包时会自动导入到项目中。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。