做者: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
那麼咱們如何在 Xcode 當中新建一個開發版的 target 呢?我會使用我提供的示例項目 "todo" 來一步一步地進行演示。你可使用本身的項目,並跟隨這些步驟進行操做:api
在 Project Navigator 面板上選擇項目,進入設置。在 Targets 小節下面,右擊現有的 target 而且選擇 Duplicate
來對一個如今的 target 進行復制。
xcode
Xcode 會詢問你這個 target 是否是針對於 iPad 開發的。對於本教程來講,咱們只須要選擇 "Duplicate Only" 就能夠了。
提示:若是你的項目支持通用設置,則 Xcode 不會提示上面的消息。服務器
如今咱們有了一個名爲 todo copy
的新 target 和構建 scheme 。讓咱們來重命名一下以便於區分。app
在 TARGETS 列表中選擇新建立的 target。按下回車鍵
來對它的名稱進行編輯,而且給它起一個合適的名稱。我傾向於使用 "todo Dev"。固然你可使用你喜歡的任何名字。
接下來,來到 "Manage Schemes…",選擇在第 1 步中新建的 scheme,並按下回車鍵
。把新 scheme 命名爲跟新 target 同樣的名字(即咱們上一小步中使用的名字)
這一步是可選的,不過我強烈建議進行這一步。若是想讓開發版跟生產版的應用更加容易區分,咱們應該提供不一樣的應用圖標和啓動界面。這可使測試更加清楚他們如今使用的版本,而且能夠防止咱們提交開發版本的應用到商店中。 ? 選中 Assets.xcassets
而後添加新的 App 圖標。選擇 icon > App Icons & Launch Images > New iOS App Icon. 將新圖標命名爲 "AppIcon-Dev" 而且添加你須要的圖片。
如今回到項目設置,選擇開發版的 target 而後修改 bundle ID。能夠簡單地在原來的 ID 上添加一個 "Dev" 後綴。若是有操做過第 4 步,在這裏確保你的 app 圖標設置爲在上一步中添加的圖標。
Xcode 會自動爲新的 target 建立一個 plist 文件(通常命名爲 todo copy-Info.plist)。能夠在項目的根目錄下找到這個文件。將 "copy" 修改成 "Dev",而後將它放到原來的 plist 文件下方。這樣能夠更方便咱們對文件進行操做。
如今選擇開發版 target 下的 "Build Settings",滾動到 "Packaging",而後修改指定 plist 文件爲開發版 plist(即剛剛的 todo Dev.plist)。
最後,爲生產版和開發版 target 同時設置一個預處理宏和編譯器標誌。這樣在以後的開發中咱們就能夠在代碼中使用這個標識來檢測當前運行的應用是哪一個版本。
對於 Objective-C 項目,來到 Building Settings
,滾動到 Apple LLVM 7.0 - Preprocessing
。展開 Preprocessor Macros
而且爲 Debug 和 Release 添加一個變量。對於開發版 target(即 todo Dev),設置變量的值爲 DEVELOPMENT=1
(校對注:等號兩邊不能有空格)。相對地,設置開發版 target 的值爲 DEVELOPMENT=0
。
對於 Swift 項目,編譯器再也不支持預處理指令了。相對地,它使用了運行期屬性(compile-time attributes)和構建配置。爲了增長開發版構建的標誌,選擇開發 target。來到 Build Settings
,向下滾動到 Swift Compiler - Custom Flags
小節。設置值爲 -DDEVELOPMENT
來代表當前爲 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 來保持各個 target 中的代碼一致。
若是你的項目中使用了 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'
若是使用了持續集成系統,好比 Travis CI 或 Jenkins,不要忘了每一個 target 的構建和交付都要配置。
你以爲這個教程怎麼樣呢?你是如何管理你的開發和生產構建版本的?能夠留言來告訴我你的想法。
本文由 SwiftGG 翻譯組翻譯,已經得到做者翻譯受權,最新文章請訪問 http://swift.gg。