對初學者而言,或許會有疑惑為什麼要把 App 的數據庫和開發環境分開處理。原因很簡單,就是為了日後 App 建立新特性或延續開發時需要在開發版本和現存版本分別進行測試。一般軟件開發都需要在不同的環境進行不同版本的測試。而 App 的開發版本通常都會和發佈版本使用不同的數據庫(或其他系統,例如分析系統)。這是其中一個原因解釋了為什麼要為不同環境使用不同的伺務器和數據庫。開發者也會在測試階段使用虛擬圖像或數據。在測試或開發環境下,不難看到 “test comment(測試評論)”,”argharghargh(隨意亂打的東西)” 和 “one more test comment(再來一個測試評論)”。當然,這些你都不會希望真實用戶看到的。假若你的 App 使用分析系統,在測試階段便可能要傳送成千上萬的事件,這些測試用的數據都是不能與正式上線的數據混淆在一起。這就是為什麼會建議把開發和上線環境分別處理的原因。
當使用兩個不同的環境時,App 需要得到指示如何連接正確的環境。一個比較流行的方法是在在主要的 app delegate 中定義一個總體變數,它將會初始化 app 的開發或上線模式。
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 版本。當在已安裝上線版本的裝置上進行開發版本測試時會造成不便。但同時這種方法也有可能導致意外地把末完成的開發版本提交至 App Store。假若遺忘更改單一的總體變數,將會錯誤地把開發版本的 App 發送至使用者。這個恐怕的錯誤我也曾犯過一次,忘了更改總體變數就呈交至 App Store,結果誤把開發版本發送出去。
在本文中,我將會告訴你一個更好的方法去區分開發和上線建置。具體而言,我們將在 Xcode 中創建一個 development target。這個方法將適用於新的和現存的專案,你可以使用任何一個現有的 App 去跟隨這篇教程。
在這個方法,App 的開發和上線版本將會使用相同的基本編碼,但分別使用不同的圖像和 bundle ID,以及指向不同的數據庫。這個分配和提交程序很簡單直接,而重點是使測試人員和管理人員可以在同一裝置中安裝同一個 App 的不同版本,而他們是能夠明確地分辦出哪個版本是在使用中。
如何建立一個新的Target
那麼如何在 Xcode 建立一個 development target?我將通過以下模板專案 “todo”,帶領你一步一步去完成整個流程。你也可以使用其他專案跟著流程去做:
1.到專案設定版面 Project Navigator 中,在 Target 區段下,右鍵點擊現存的 target 並按下 Duplicate
去複製已建立的 target 。
2.Xcode 會詢問你新的 target 是否要配置給 iPad 開發。在這個教程中,我們只用選擇 “Duplicate Only”。
3.現在我們有一個新的 target 和一個新的 todo copy
scheme。我們把它的名字更換以便理解。
- 在 TARGETS 列表中選擇新的 target。按下
Enter
編輯文字並寫入適當的名字。我推薦用 “todo Dev”,當然你也可以選擇任何名字。 - 接下來,在 “Manage Schemes…” 中,選擇第一個步驟中建立的新 scheme 並按下 “Enter”,將其名字更改至和新 target 一樣的名字(就是那個你選擇的新 target)。
4.第4步是選擇性的,而我當然是鼓勵你跟著去做。如果你想要在開發和上線建置之間更容易分辨真假數據,你應該為每個版本使用不同的圖像和啟動畫面。這個做法以便測試人員更明確地知道這是一個開發版本,同時間亦防止錯誤地把開發版本發送出去。
到 Assets.xcassets
中加入新的圖像。右鍵點擊圖像,之後選擇 App Icons & Launch Images,接著選擇 New iOS App Icon。將新圖像更名為 “AppIcon-Dev” 並加入自訂圖片。
5.回到專案設定版面,選擇你的開發 target 並更改其 bundle ID。你可以在原本的 ID 中加入 “Dev” 字眼。如果你執行了步驟4,確保你將 App 圖像設置為與上一步中所創建的相同圖像。
6.Xcode 會自動為你的 target 加入一個 plist 檔(例如 todo copy-Info.plist)。你可以在專案的根文件夾下找到它,然後將其名字從 “copy” 改為 “Dev”,並遷移至原本的 plist 文件夾下。這個做法讓你便於管理檔案。
7.現在打開你開發 target 中的 “Build Setting”,捲動到 “Packaging”,把原本的值改為開發的 plist 檔(例如 todo Dev.plist)。
8.最後,我們會為開發和上線 target 同時配置 preprocessing macro/compiler flag,之後便可以透過標誌檢測正在運行中的 App 是哪一個版本。
如果是 Objective-C 專案,到 Build Settings
然後捲動到 Apple LLVM 7.0 - Preprocessing
,展開 Preprocessor Macros
,分別為 Debug 和 Release 加入變數。 在開發target中(例如 todo Dev), 將其值設置為 DEVELOPMENT=1
。在另一面,將值設置為 DEVELOPMENT=0
以表明其為上線版本。
在 Swift 專案中,編譯器不再支援 preprocessor 的指令。取而代之的是 compile-time 屬性和構建組態。選擇開發 target,加入一個標誌以表明其為開發構建。到 Build Settings
中,捲動到 Swift Compiler - Custom Flags
,將值設置為 -DDEVELOPMENT
以表明這是開發建置的 target。
完成了建立並配置開發建置,現在將進入下一個程序。
使用 Target 和 Macro
我們會在專案中利用 macro DEV_VERSION
配置中的編碼和進行動態編譯,舉例來說:
Objective-C:
#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
去檢查 DEV_VERSION
的狀態,並以此設置 URL 與 API 的鑰匙。
Swift:
#if DEVELOPMENT
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
去定義一個基元常數,我們一般會在 Swift 中使用 let
去定義整體常數。
現在當你選擇 “todo Dev” scheme 並運行專案,開發建置將會自動使用伺服器配置去建立開發環境。現在開發版本已經為測試人員和管理人員準備好,並上傳到 TestFlight 或 HockeyApp。
之後如果你需要建立一個上線建置,只需選擇 “todo” scheme 便可,而不需要為任何編碼作出更改。
關於管理多個 Target 的注意事項
1.當在專案新增文件時,別忘記同時在開發和上線建置中選擇 target 讓編碼得到同步更新。
2.若果你是使用 Cocoapods,別忘記將新的 target 加入到 podfile,透過 link_with
以規定多個 target。你可以在 Cocoapods documentation 中進一步了解詳細資訊。而 podfile 看起來像這樣:
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '7.0' workspace 'todo' link_with 'todo', 'todo Dev' pod 'Mixpanel' pod 'AFNetworking'
3.如果你使用連續整合系統(continuous integration system),例如Travis CI 或 Jenkins ,別忘記為兩個 target 配置構建。
這次的教程效果如何呢?你又是怎麼管理你的開發和上線建置呢?歡迎給予評論和分享意見。
原文:How to Use Xcode Targets to Manage Development and Production Builds