使用 Xcode 的 Target 区分开发和生产环境

做者:Eugene Trapeznikov,原文连接,原文日期:2016-01-18
译者:小锅;校对:Channe;定稿:numbbbbbios

一些初学者可能会好奇,为何在开发应用的时候咱们须要用两套隔离的数据库和环境。这是由于在你持续地开发应用或增长新特性的时候,可能但愿将开发版本和已经存在的生产版本的应用进行区分。标准的开发实践是针对不一样版本的软件使用不一样的环境,而对咱们来讲,这个软件就是 iPhone 应用。通常来说,开发版应用使用的数据库(或其它系统,好比说统计分析系统)应该与生产版应用进行区分。在测试或者开发环境中,咱们常用到相似 "test comment", "argharghargh" 和 "one more test comment" 这样的测试数据。很显然,咱们并不想让真实的用户看到这样的信息。若是应用使用了统计分析系统,在测试阶段咱们可能会发送成千上万次的统计事件。咱们固然也不想让这样的数据跟真实的统计数据混在一块儿。这就是为何咱们应该区分开发环境和生产环境。git

当使用不一样的环境开发时,应用须要知道它当前使用的环境。一种通用的作法是在程序的 AppDelegate 中定义一个能够将应用初始化为开发或者生产模式的全局变量。github

enum environmentType {
    case development, production
}
 
let environment:environmentType = .production
 
switch environment {
case .development:
    // set web service URL to development
    // set API keys to development
    print("It's for development")
case .production:
    // set web service URL to production
    // set API keys to production
    print("It's for production")
}

这种方法要求咱们在切换环境的时候改变全局变量的值。虽然这种方法很方便也很快捷,可是它存在很大的局限性。首先,由于在开发与生产环境中都使用了同一个 bundle ID,咱们就不能在同一个设备上同时安装应用的不一样版本。再者,这种方法有可能致使咱们不当心把开发版本的应用提交到 App Store 上。若是忘记切换全局变量的值,咱们就会提交错误版本的应用。我曾经就有一次在提交应用以前忘记改变全局变量的值,结果用户就使用到了个人开发版本。这实在是太糟糕了。web

在本篇文章中我将会展现一种更好的方法来区分开发和生产的构建版本。更确切地来讲,咱们将会在 Xcode 中建立一个开发版的 target。这个方法同时适用于新建的或现存的大型项目,因此你可使用一个现有的项目来跟着这个教程进行实践。数据库

使用这种方法,生产版和开发版的应用都会使用同一套基础代码,可是能够有不一样的图标、bundle ID 以及不一样的数据库。分发和提交应用的过程也会十分简单。更重要地,应用的测试人员和管理人员能够在同一个设备上同时安装应用的两个版本,这样他们就能够更加清楚地了解他们如今试用的是哪个版本。swift

如何建立新的 Target

那么咱们如何在 Xcode 当中新建一个开发版的 target 呢?我会使用我提供的示例项目 "todo" 来一步一步地进行演示。你可使用本身的项目,并跟随这些步骤进行操做:api

  1. 在 Project Navigator 面板上选择项目,进入设置。在 Targets 小节下面,右击现有的 target 而且选择 Duplicate 来对一个如今的 target 进行复制。
    Duplicate-targetxcode

  2. Xcode 会询问你这个 target 是否是针对于 iPad 开发的。对于本教程来讲,咱们只须要选择 "Duplicate Only" 就能够了。
    Duplicate-only
    提示:若是你的项目支持通用设置,则 Xcode 不会提示上面的消息。服务器

  3. 如今咱们有了一个名为 todo copy 的新 target 和构建 scheme 。让咱们来重命名一下以便于区分。app

    • TARGETS 列表中选择新建立的 target。按下回车键来对它的名称进行编辑,而且给它起一个合适的名称。我倾向于使用 "todo Dev"。固然你可使用你喜欢的任何名字。

    • 接下来,来到 "Manage Schemes…",选择在第 1 步中新建的 scheme,并按下回车键。把新 scheme 命名为跟新 target 同样的名字(即咱们上一小步中使用的名字)
      Target and scheme

  4. 这一步是可选的,不过我强烈建议进行这一步。若是想让开发版跟生产版的应用更加容易区分,咱们应该提供不一样的应用图标和启动界面。这可使测试更加清楚他们如今使用的版本,而且能够防止咱们提交开发版本的应用到商店中。 ? 选中 Assets.xcassets 而后添加新的 App 图标。选择 icon > App Icons & Launch Images > New iOS App Icon. 将新图标命名为 "AppIcon-Dev" 而且添加你须要的图片。
    image-asset-dev

  5. 如今回到项目设置,选择开发版的 target 而后修改 bundle ID。能够简单地在原来的 ID 上添加一个 "Dev" 后缀。若是有操做过第 4 步,在这里确保你的 app 图标设置为在上一步中添加的图标。
    New App ID Icon

  6. Xcode 会自动为新的 target 建立一个 plist 文件(通常命名为 todo copy-Info.plist)。能够在项目的根目录下找到这个文件。将 "copy" 修改成 "Dev",而后将它放到原来的 plist 文件下方。这样能够更方便咱们对文件进行操做。

  7. 如今选择开发版 target 下的 "Build Settings",滚动到 "Packaging",而后修改指定 plist 文件为开发版 plist(即刚刚的 todo Dev.plist)。
    new plist

  8. 最后,为生产版和开发版 target 同时设置一个预处理宏和编译器标志。这样在以后的开发中咱们就能够在代码中使用这个标识来检测当前运行的应用是哪一个版本。

    对于 Objective-C 项目,来到 Building Settings,滚动到 Apple LLVM 7.0 - Preprocessing。展开 Preprocessor Macros 而且为 DebugRelease 添加一个变量。对于开发版 target(即 todo Dev),设置变量的值为 DEVELOPMENT=1(校对注:等号两边不能有空格)。相对地,设置开发版 target 的值为 DEVELOPMENT=0

    dev-macro-1

dev-macro-2

对于 Swift 项目,编译器再也不支持预处理指令了。相对地,它使用了运行期属性(compile-time attributes)和构建配置。为了增长开发版构建的标志,选择开发 target。来到 Build Settings,向下滚动到 Swift Compiler - Custom Flags 小节。设置值为 -DDEVELOPMENT 来代表当前为 target 为开发版。

swift-compiler-flag

如今咱们已经建立并配置好了开发版的 target,接下来要作什么呢?

使用 Target 和宏

由于设置过了 DEV_VERSION 的宏,咱们就能够在代码中利用这个宏对项目使用动态检测了。这里有一个简单的使用示例:

Objective-C:

objc
#if DEVELOPMENT
#define SERVER_URL @"http://dev.server.com/api/"
#define API_TOKEN @"DI2023409jf90ew"
#else
#define SERVER_URL @"http://prod.server.com/api/"
#define API_TOKEN @"71a629j0f090232"
#endif

在 Objective-C 当中,咱们可使用 #if 来对 DEVELOPMENT 的状态进行检测,而且为 URL/API 设置对应的值。

Swift:

#if DDEVELOPMENT
let SERVER_URL = "http://dev.server.com/api/"
let API_TOKEN = "DI2023409jf90ew"
#else
let SERVER_URL = "http://prod.server.com/api/"
let API_TOKEN = "71a629j0f090232"
#endif

在 Swift 当中,咱们依然可使用 #if 来对构建配置进行动态判断。然而,咱们再也不使用 #define 来定义一个常量,而是简单地使用 let 来定义一个 Swift 中全局常量。

提示:通常状况下,咱们会将上面的代码放在 AppDelegate 当中。不过最终取决于你想在哪里初始化应用的配置。

当选择 "todo Dev" 的 scheme 并运行项目,咱们就会建立一个开发版的构建并自动将服务器配置设置为开发版的环境。你如今能够放心地上传这个开发版到 TestFlight 或者 HockeyApp 让应用的测试人员或者管理人员进行测试了。

之后若是须要建立一个生产版的构建,只要简单地选择 "todo" 的 scheme。一行代码都不须要改变。

关于管理多个 Target 的一些注意事项

  1. 当为项目添加新文件时,不要忘记同时勾选多个 target 来保持各个 target 中的代码一致。

  2. 若是你的项目中使用了 Cocoapods,不要忘记在 podfile 中增长新的 target。咱们可使用 link_with 来指定多个 target。能够在 Cocoapods 文档中找到更详细的内容。如今 Podfile 看起来应该是这样的:

    source 'https://github.com/CocoaPods/Specs.git'
    platform :ios, '7.0'
    workspace 'todo'
    link_with 'todo', 'todo Dev'
    pod 'Mixpanel'
    pod 'AFNetworking'
  3. 若是使用了持续集成系统,好比 Travis CIJenkins,不要忘了每一个 target 的构建和交付都要配置。

你以为这个教程怎么样呢?你是如何管理你的开发和生产构建版本的?能够留言来告诉我你的想法。

本文由 SwiftGG 翻译组翻译,已经得到做者翻译受权,最新文章请访问 http://swift.gg

相关文章
相关标签/搜索