[譯] 輕鬆管理 Swift 專案中的不同環境

金西西發表於2018-05-09

[譯] 輕鬆管理 Swift 專案中的不同環境

想象一下,你已經完成了應用程式的開發和測試,現在你已準備好將其提交併釋出。但有個問題:你所有的 API key、URL、圖示或其他設定都是針對測試環境進行配置的。因此,在提交應用程式之前,你必須將所有這些內容切換到生產環境。顯然,這聽起來就不太好。此外,你可能會在你龐大的應用中忘記一兩個更改,你所提供的服務自然將無法正常工作。

與其使用這種混亂的方法,不如設定幾個環境,並在需要時簡單地更改它們。今天,我們將最常用的幾個方法來嘗試管理環境配置:

  1. 使用註釋。
  2. 使用全域性變數或列舉。
  3. 使用 target 配置和 scheme 並結合全域性標誌。
  4. 使用 target 配置和 scheme 並結合多個 *.plist 檔案。

1. 使用註釋

當你有兩個不同的環境時,應用程式需要知道它應該連線到哪個環境。想象一下,你有 ProductionDevelopmentStaging 環境和多個 API 端點。處理這個問題的最快速和簡單的方法是使用 3 個不同的變數,並註釋掉其中的 2 個:

// MARK: - Development
let APIEndpointURL = "http://mysite.com/dev/api"
let analyticsKey = "jsldjcldjkcs"

// MARK: - Production
// let APIEndpointURL = "http://mysite.com/prod/api"
// let analyticsKey = "sdcsdcsdcdc"
// MARK: - Staging
// let APIEndpointURL = "http://mysite.com/staging/api"
// let analyticsKey = "lkjllnlnlk"
複製程式碼

這種方法很髒亂,會讓你哭得很厲害。有時我在黑客馬拉松上用它,那對程式碼的質量沒有任何要求,只看重速度和靈活性。在任何其他情況下,我強烈建議不要使用它。

2.使用全域性變數或列舉

另一種流行的方法是有一個全域性變數或 Enum(這個會更好)來處理不同的配置。你需要在你的 Enum 中宣告 3 個環境(例如在 AppDelegate 檔案中)設定它的值:

enum Environment {
    case development
    case staging 
    case production
}
 
let environment: Environment = .development
 
switch environment {
case .development:
    // 將 web 服務 URL 設定為開發環境
    // 將 API key 設定為開發環境
    print("It's for development")
case .staging:
    // 將 web 服務 URL 設定為預上線環境
    // 將 API key 設定為開發環境
    print("It's for staging")
case .production:
    // 將 web 服務 URL 設定為生產環境
    // 將 API key 設定為開發環境
    print("It's for production")
}
複製程式碼

這種方法讓你每次要更改程式碼時只需設定一次環境。與以前的方法相比,這個更好,更快而且可讀性更強,但也有很多限制。首先,在執行任何環境時,你始終擁有相同的 Bundle ID。這意味著你無法同時在裝置上擁有 2 個分別對應不同環境的應用,這簡直讓人難受。

此外,為每個環境設定不同的圖示也是一個不錯的主意,但採用這種方法,你無法更改圖示。而且,如果你在釋出應用程式之前忘記更改這個全域性變數,那你肯定會遇到問題。


讓我們繼續嘗試另外兩種方法來更快地切換環境。這兩個方法對於新建的專案和現有的大型專案都適用。所以跟著本教程,你可以很容易地應用在你現有的一個專案上。

應用這些方法之後,你的應用的每個環境將會使用相同的程式碼庫,但對於每種配置,能夠擁有不同的圖示和不同的 Bundle ID。分發過程也非常簡單。而最重要的是,專案經理和測試人員將能夠將你不同環境配置的應用獨立安裝在他們的裝置上,所以他們會完全理解他們試用的版本。

3.使用 target 配置和 scheme 並結合全域性標誌

在這種方法中,我們需要建立 3 個不同的 configuration 和 3 種不同的 scheme,並將 scheme 和對應 configuration 連線起來。我將建立一個叫“Environments”的專案來演示這一過程,你也可以建立一個新專案或在現有專案中實現。

在 Project Navigator 皮膚中點選你的專案跳到專案設定。在 target 部分中,右鍵單擊現有 target 並選擇 Dublicate 來複制當前 target。

[譯] 輕鬆管理 Swift 專案中的不同環境

現在我們有一個新的 target 和一個叫做“Environments copy”的 scheme。讓我們重新命名為一個合適的名字。左鍵單擊你的新 target,回車,將其名稱更改為“Environments Dev”。

接下來,點選“Manage Schemes…”,選擇在上一步中建立的新 scheme,然後按回車,重新命名使其與新建立的 target 同名避免混淆。

[譯] 輕鬆管理 Swift 專案中的不同環境

然後,讓我們建立一個新的圖示資源,以便測試人員和管理員方便地知道他們啟動的 app 對應的配置。

進入 Assets.xcassets,點選“+”並選擇“New iOS App Icon”。將其名稱更改為“AppIcon-Dev”。

[譯] 輕鬆管理 Swift 專案中的不同環境

現在我們可以將這個新的圖示資源與我們的開發環境對應起來。進入“Targets”,左鍵單擊你的 Dev taget,找到“App Icon Source”並選擇你的新的圖示資源。

[譯] 輕鬆管理 Swift 專案中的不同環境

就是這樣,現在每個 configuration 都有不同的圖示。請注意,當我們建立第二個 configuration 時,第二個 *.plist 檔案也是為我們的第二個環境生成的。

重要提示:現在我們有兩種不同的方法來處理兩種不同的配置:

  1. 為生產和開發目標新增預處理巨集/編譯器標誌。
  2. 將變數新增到 *.plist 中。

我們將從第一個方法開始講這兩種方法。

新增一個代表開發環境的標誌,首先需要選擇剛才建立的開發環境的 target,進入“Build Settings”並找到“Swift Compiler — Custom Flags”部分。將該值設定為“-DDEVELOPMENT”,將你的目標標記為開發環境。

[譯] 輕鬆管理 Swift 專案中的不同環境

然後在程式碼中像這樣配置不同的環境:

#if DEVELOPMENT
let SERVER_URL = "http://dev.server.com/api/"
let API_TOKEN = "asfasdadasdass"
#else
let SERVER_URL = "http://prod.server.com/api/"
let API_TOKEN = "fgbfkbkgbmkgbm"
#endif
複製程式碼

現在,如果您選擇 Dev scheme 並執行你的程式,應用程式將會自動運在開發環境配置下。

4.使用 target 配置和 scheme 並結合多個 *.plist 檔案

在這種方法中,我們需要重複上一個方法的前幾個步驟,建立和上個方法相同的幾種 configuration 和 scheme。然後,我們不需要再新增全域性標誌,而是需要新增必要的值到我們的 .plist 檔案中。另外,我們將在兩個 *.plist 檔案中分別新增一個 String 型別的 serverBaseURL 變數,並填上 URL。現在每個 *.plist 檔案都包含一個 URL,我們需要從程式碼中呼叫它。我認為,為我們的 Bundle 建立一個 extension 將是一個不錯的主意,如下所示:

extension Bundle {
    var apiBaseURL: String {
	return object(forInfoDictionaryKey: "serverBaseURL") as? String ?? ""
    }
}

//And call it from the code like this:
let baseURL = Bundle.main.apiBaseURL
複製程式碼

就我個人而言,我更喜歡這種方法,因為在你不應該在程式碼中檢查你的配置。你只需詢問 Bundle,只用一行程式碼,就可以根據當前配置得到需要的結果。

在使用多個 target 的時候

  • 請記住,儲存在 *.plist 檔案中的資料可能會被讀取,並且可能非常不安全。一種解決方案是,把敏感金鑰放在程式碼中,並僅將其鍵名放在 *.plist 檔案中。
  • 新增新檔案時,請不要忘記選擇兩個 target 以保持你的程式碼在兩種配置中同步。
  • 如果你使用了持續整合服務,例如 Travis CIJenkins,請不要忘記為它們正確地配置。

結論

從一開始就以可讀和靈活的方式將你的 app 分成不同環境總是有用的。即使用最簡單的技術,我們也可以避免許多配置中的典型問題,並顯著提高我們的程式碼質量。

今天,我們簡要地從最簡單的方法介紹了幾種方法,可能還有更多其它的方法來管理配置。我很期待在評論中看見你的方法。

謝謝閱讀 :)


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章