輕松管理Swift項目中的各種環境

這是我基于英文原文翻譯的譯文,如果你對本文感興趣而且想轉發,你應該在轉發文章里加上本文的鏈接

英文原文鏈接

想象一下當你完成開發和測試,準備提交到生產環境時的場景時,你會遇到這么一個問題:所有你的API keys,URL,icon或者其他啟動配置都是開發環境的。所以在你發布你的app的時候,你不得不為了適應生產環境而把他們全部改過來。顯然,這做法不太好。有時候,由于你的app太復雜,你可能會忘記一些改動,從而導致服務不能正常工作。

不像這些糟糕的做法,本文的做法將會根據我們的需要去配置不同的環境,并且改動配置非常簡單。現在,我們將討論幾種最常見的環境配置管理的方法:

  • 1、使用注釋
  • 2、使用全局變量或枚舉
  • 3、通過一個全局標記flag使用配置和schemes
  • 4、通過 *.plist 文件使用配置和schemes

1、使用注釋

當你有兩個獨立的環境,你的應用需要知道它應該使用那個環境。想象一下,你有生產,開發,演示三個環境和API接口。那么環境切換的最快最簡單方法就是注釋其他兩個環境。

// 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、使用全局變量或枚舉

另一種流行的做法,是通過一個全局變量或枚舉(這個會好一點)來處理不同的配置環境。你需要在某個地方(例如AppDelegate)聲明您的三個不同環境的枚舉和設置它們的值。


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

這種做法保證你可以只改變一處代碼就能配置不同的環境。與之前的方法不同,這個會好很多。這種做法非常靈活,可讀性更強,但它有很多局限性。首先,在不同環境下運行都只有一個相同的Bundle ID。這就意味著你講不能同時裝上不同環境的相同app。這種做法其實也是不太合適。

除此以外,這種做法也不能根據不同的環境改變app的icons。而且,如果你在提交app之前忘記更改這個全局變量,你肯定會出問題。


我們再看看其他兩種更好的實現方法。這些方法對于新項目和舊項目都適合。跟著這個教程,你可以很容易將它應用到就項目中。

After applying these approaches your app will have the same codebase for every environment, but you will be able to have different icons and different Bundle ID’s for every configuration. The distribution process also will be very easy. And what is the most important, your managers and testers will be able to have all your environments as separated apps on their devices. So they will fully understand which version they’re trying out.

使用這些方法后,你的app只有一份代碼庫,但你可以根據不同環境配置有不同icons和Bundle ID。這會讓你的發布變得非常簡單。最重要的是,你的老大和測試可以有多個不同環境的相同app,因此他們非常清楚他們正在測試的是那個版本的應用。

3、通過一個全局標記flag使用配置和schemes

在這種做法中,我們將創建三個不同的配置,三個不同的schemes和與schemes相關的配置。為了演示這種做法,我將新建一個“Environments”項目,你也可以創建一個新項目或者在老項目中做。

在項目導航的面板中找到項目設置,在targets的列表中右擊已存在的target,然后選擇 Duplicate 來復制當前target。

現在我們有不止一個的target和叫‘Environments copy’的build scheme。我們先把它們改成對應的名字。點擊您的新target和按下“Enter”鍵,改target的名字為“Environments Dev”。然后,去到“Manage Schemes…”,選擇剛才新創建的scheme,按下“Enter”,重命名你的target,避免命名混亂。

同樣的,我們可以新建一個icon asset,這樣測試和老大就能知道打開的是哪個app配置。去到Assets.xcassets,點擊 “+” ,選擇“New iOS App Icon”。修改它的名字為“AppIcon-Dev”。

現在我們要建立新的icons asset和我們開發環境的聯系。去到“Targets”,點擊你的開發環境,找到“App Icon Source”選擇新的icons asset。

就是這樣,現在你有每個環境的不同icons。請注意,當我們新建第二個配置時,第二個 *.plist 文件也會生成出來。

值得注意,我們現在有兩種不同的做法去處理兩種不同的配置:

  • 1、添加一個預編譯宏標記去區分生產和開發targets。
  • 2、在 *plist 文件中添加一個變量。

我們嘗試第一種方法。我們添加一個標記變量去標記選擇的開發環境。在“Build Settings”中,找到“Swift Compiler?—?Custom Flags”這個選項。設置 -DEVELOPMENT 來標記這個target是開發的build。

然后配置的代碼就像如下所示:


#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運行,你就自動使用開發配置來啟動你的app了。

4、通過 *.plist 文件使用配置和schemes

在這種做法中,我們將重復之前那個創建新scheme的步驟。在做完這個步驟后,不像之前一樣添加一個全局標記,我們將把必要的值添加進我們的*.plist中。同樣的,我們將添加一個 serverBaseURL 字符串變量到每個 .plist 文件中,并把URLs作為值進行設置。現在每個.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,然后它就會返回他自己當前的配置。

當使用多個targets時需要注意一些情況

  • 記住在一個 *.plist 文件中你的數據存儲能被讀取是很可能不安全的。解決方法就是,把你的敏感的值放到代碼中,只把不敏感的放到 *.plist 文件中。
  • 當添加一個新的文件時,不要忘記添加到所有的target中,以保證你的代碼在所有配置環境中都是一樣的。
  • 如果你使用持續集成服務,例如 Travis CI 或 Jenkins,不要忘記正確配置它們。

Conclusion

結論

一開始用一種可讀性強且靈活的方法,去區分不同app環境,是很有必要的。甚至是那種我們避免使用的,最簡單的處理不同配置的方法,都能很好的提高我們的代碼質量。

我們從最簡單的開始,討論了幾種不同的做法。但是,還有很多其他不同環境配置方法我們沒有涉及到,我很希望在下面評論中看到其他的做法。

感謝大家的閱讀 :)

本文Github地址

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,559評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,442評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,835評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,581評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,922評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,096評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,639評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,374評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,591評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,789評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,196評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,524評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,322評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,554評論 2 379

推薦閱讀更多精彩內容