此篇文章完整範例呈現於GitHub,若有需要參考可直接clone 並切換到每個階段,有任何問題也歡迎直接在底下留言或在GitHub 開issue。
問題
在專案當中,有時候我們會透過類似以下的用法來判定是否為某一個開發環境:
struct Config {
static let isProduction = false
static let apiURL = isProduction ? "www.production.server.com" : "www.test.server.com"
}
如果我們需要release 不同環境的app 時,我們必須要手動去更改isProduction
的值,有時候一個不小心Build 了十幾分鐘發現自己忘了改、改錯了、不小心把設定Commit 了… 等等團隊開發中容易誤導的問題,都相當的困擾,因此應該用良好的方法來避免這樣的問題發生。
一個透過CocoaPods 管理相依的專案,他的初始狀態看起來會像這樣:
在Project Info 當中,會有一個Configurations 的區塊,而CocoaPods 在你使用pod install
指令時也偷偷暗藏了他們的設定檔在這邊。
我們可以看到,專案預設是兩種設定檔,分別是Debug
與Release
,這兩者的區分如下:
當你點擊Edit Scheme
時,可以看到:
Run
與Archive
使用了不同的Build Configuration,這也是一個iOS 專案的預設設定。
這樣的設定有什麼問題?如果公司內部平常都會打包ipa 並上傳至TestFlight 之類的平台測試,並且有可能連上「Production」或「Development」環境,這樣子你在Archive 時,兩種都是使用Release 的設定檔,那我們就沒辦法分辨出是哪個環境了.因此就必須要手動去切換上述的isProduction
這個flag,相當麻煩且危險。
解法
首先,我們回到Configuration ,點擊加號分別使用Duplicate "Debug" Configuration
與Duplicate "Release " Configuration
來新增兩個完全相同的設定檔。
至於命名的部分,可以依據喜好決定要叫做什麼名字,範例則使用如下圖所示:
設定完之後,我們打開Podfile
並加上:
target 'SeparateEnvironment' do
use_frameworks!
project 'SeparateEnvironment', 'ProductionDebug' => :debug, 'ProductionRelease' => :release
pod 'IGListKit'
end
我們必須指定額外新增的兩個Configuration 屬於debug 或release 環境,並且重新下pod install
指令來重新產生Project file。
接下來我們回到Project Info 並選擇我們的App target,然後搜尋condition
:
換看到在預設的狀態下,Debug
已經是一個預設的Condition ,我們可以在Swift code 當中使用:
struct Config {
#if DEBUG
static let isProduction = false
#else
static let isProduction = true
#endif
static let apiURL = isProduction ? "www.production.server.com" : "www.test.server.com"
}
但這並不符合我們的需求,我們希望在不同的設定檔下決定連上哪台server ,而不是分是不是Debug 狀態,因此我們只要加上我們自己的condition ,就可以達到預期效果:
struct Config {
#if DEV_ENV
static let isProduction = false
#else
static let isProduction = true
#endif
static let apiURL = isProduction ? "www.production.server.com" : "www.test.server.com"
}
加好設定檔之後,我們再回到Edit Scheme...
->Manage Schemes...
,點選加號之後,取一個如下圖的名字:
記得,後面的Shared
可以打勾,就可以跟團隊的人共享,不需要每個人都創建自己的Schame。
加完了Scheme 之後,必須再重新打開Edit Scheme...
,並選擇剛剛新增的Scheme,點擊一下左邊的所有動作,並把相對應的Build Configuration
挑選成你要的,這樣才算是大功告成,下圖以Run
為例:
結論
做完上述的操作後,我們會有兩個Scheme,未來只要需要Build production 環境的話,就只要切換Scheme 即可,大幅降低弄錯得機會,再加上如果使用fastlane
等工具,只要新增prod
與dev
兩個lane ,並且build 不同的Scheme 即可:
lane :dev do |options|
options[:scheme] = "SeparateEnvironmente"
build(options)
end
lane :prod do |options|
options[:scheme] = "[Prod] SeparateEnvironment"
build(options)
end
private_lane :build do |options|
scheme = options[:scheme]
# before archive ...
gym(scheme: scheme)
# after archive ...
end
收工!😎