前言
一個(gè)APP的開發(fā)涉及到多種環(huán)境在所難免,比如Test環(huán)境宴抚,UAT(User Acceptance Test)用戶驗(yàn)收測(cè)試環(huán)境布轿,Release環(huán)境等等。我的項(xiàng)目需求是朝聋,在不同的環(huán)境下在代碼中使用全局性常量值不同嗡午,比如說(shuō)請(qǐng)求所用的IP。這里只是作一個(gè)簡(jiǎn)單的記錄和分享冀痕。
Configuration配置
配置Configuration的目的是為了增加或刪除編譯環(huán)境荔睹,對(duì)于不同編譯環(huán)境下的參數(shù)需求可以到xcconfig中進(jìn)行設(shè)置。
1言蛇、進(jìn)入工程的info頁(yè)僻他,下面紅框中標(biāo)明的是工程創(chuàng)建時(shí)自帶的兩個(gè)編譯環(huán)境Debug和Release。
點(diǎn)擊下面的加號(hào)添加新的編譯環(huán)境猜极,根據(jù)需要選擇Duplicate Debug和Duplicate Release中姜,他們的區(qū)別在于消玄,后者會(huì)進(jìn)行各種優(yōu)化跟伏,包括編譯的優(yōu)化,導(dǎo)致不能調(diào)試(不能通過(guò)斷點(diǎn)翩瓜、LLDB查看變量)受扳,另外Release環(huán)境下打的包也會(huì)更輕量一些。這里我將Debug環(huán)境名改為UAT_α兔跌,并增加一個(gè)基于Debug 的UAT_β環(huán)境勘高。
插曲:如果想要在Relase環(huán)境下去調(diào)試可以前往Bulid Setting總進(jìn)行設(shè)置,將Release下的參數(shù)換成和Debug一樣即可:
2、配置預(yù)編譯宏坟桅,這就相當(dāng)于在pch文件當(dāng)中去定義宏华望,可以在項(xiàng)目中做不同環(huán)境的區(qū)分,進(jìn)而進(jìn)行操作仅乓。進(jìn)入工程的Build Setting ->Preprocessor Macros:
我們看到UAT_α和UAT_β對(duì)應(yīng)的值均為DEBUG = 1赖舟,我們可以理解的是在兩種環(huán)境下同時(shí)定義了#define DEBUG 1,為了表示區(qū)別可以分別設(shè)置為不同的宏名和值夸楣,例如:ConfigDemo_ UAT_α=0,ConfigDemo_ UAT_β=1(等號(hào)兩邊不能留空格宾抓,否則會(huì)編譯出錯(cuò))子漩。GCC提供了一種動(dòng)態(tài)編譯的方法:ConfigDemo_{CONFIGURATION}=1,這兩種設(shè)置方法是等價(jià)的(注意不要?jiǎng)?(inherited)石洗,他表示繼承工程的默認(rèn)設(shè)置)幢泼。
3、進(jìn)行Scheme的配置讲衫,可以理解一個(gè)Scheme對(duì)應(yīng)一個(gè)Target缕棵、一種環(huán)境(當(dāng)然這里只有一個(gè)Target,只是編譯環(huán)境不同)涉兽。 當(dāng)我們切換不同的Scheme運(yùn)行時(shí)就是切換不同的環(huán)境了挥吵。在Xcode的左上角選擇添加新的Scheme,并分別添加ConfigDemo_ UAT_α花椭,ConfigDemo_ UAT_β兩個(gè)Scheme:
添加完Scheme后對(duì)其進(jìn)行配置忽匈,我們剛才配置環(huán)境后總共有Release、UAT_α矿辽、UAT_β三種環(huán)境丹允,在這里使他們分別對(duì)應(yīng)ConfigDemo、ConfigDemo_ UAT_α袋倔,ConfigDemo_ UAT_β雕蔽,選擇Edit Scheme,這里可以將Run宾娜、Test批狐、Archive改為對(duì)應(yīng)的Scheme,關(guān)于他們的解釋:
于是在代碼中就可以進(jìn)行如下操作:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
#ifdef ConfigDemo_UAT_α
#define TestString @"ConfigDemo_UAT_α"
#elif ConfigDemo_UAT_β
#define TestString @"ConfigDemo_UAT_β"
#else //Release
#define TestString @"Release"
#endif
NSLog(@"TestString:%@",TestString);
// 打印結(jié)果分別為Release前塔、ConfigDemo_UAT_α嚣艇、ConfigDemo_UAT_β
}
根據(jù)不同的Scheme配置不同的displayName、APPICON等可以參見文章最后的鏈接;
配置xcconfig
關(guān)于項(xiàng)目的參數(shù)需要做一下說(shuō)明:
xcconfig文件的修改實(shí)際上是修改build setting中的參數(shù)华弓。Projects 會(huì)包含一個(gè)或者多個(gè) targets,這里可以理解每一種編譯環(huán)境對(duì)應(yīng)一個(gè)target食零,每一個(gè) target 將會(huì)產(chǎn)出一個(gè) product.這些指令以 build setting 和 build phases 的形式存在,你可在 Xcode 的項(xiàng)目編輯器(TARGETS->Build Setting, TARGETS->Build Phases)中進(jìn)行查看和編輯寂屏。target 中的 build setting 參數(shù)繼承自 project 的 build settings, 但是你可以在 target 中修改任意 settings 來(lái)重寫 project settings贰谣,這樣,最終生效的 settings 參數(shù)以在 target 中設(shè)置的為準(zhǔn). Project 可包含多個(gè) target, 但是在同一時(shí)刻迁霎,只會(huì)有一個(gè) target 生效吱抚,可用 Xcode 的 scheme 來(lái)指定是哪一個(gè) target 生效,雖然這里并沒有配置多個(gè)Target,但是這里還是可以理解一個(gè)Scheme對(duì)應(yīng)一個(gè)Target考廉。
另外要說(shuō)明一點(diǎn)秘豹,對(duì)于項(xiàng)目中其他地方的配置,可以直接在操作板中復(fù)制粘貼到文件中來(lái)進(jìn)行修改芝此,最終xcconfig的設(shè)置會(huì)覆蓋原來(lái)的設(shè)置憋肖。
對(duì)于需要單獨(dú)配置參數(shù)的環(huán)境則生成一個(gè)xcconfig文件因痛,沒有單獨(dú)配置xcconfig的則使用默認(rèn)的設(shè)置,另外在這里需要生成一個(gè)公用的xcconfig文件岸更。公共文件用于定義好統(tǒng)一的變量(宏)鸵膏,每一個(gè)環(huán)境去設(shè)置具體的值,形成多環(huán)境配置怎炊。
每個(gè)文件代碼的寫法:
- Common. xcconfig的寫法
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) VariableA='$(VariableA)' VariableB='$(VariableB)'
解析如下:
其作用是將配置文件中定義的常量定義成預(yù)編譯宏谭企,以便于在代碼中獲取。
GCC_PREPROCESSOR_DEFINITIONS 是 GCC 預(yù)編譯頭參數(shù)评肆,對(duì)應(yīng)的設(shè)置在 Xcode8下的路徑為 Build Settings->Apple LLVM 7.x Preprocessing->Preprocessor Macros债查,就是我上面提到的設(shè)置預(yù)編譯宏,這里權(quán)且可以理解上面這一串代碼是在Build Setting中設(shè)置預(yù)編譯宏的代碼化瓜挽,而這里的設(shè)置并不會(huì)覆蓋之前在Build Setting中的設(shè)置盹廷,只會(huì)將這些新增的設(shè)置添加到最后面。 上面代碼的意思是久橙,定義兩個(gè)預(yù)編譯的宏名字分別為VariableA俄占、VariableB,他們具體的值就可以在不同的xcconfig中去設(shè)置淆衷,不同的xcconfig需要導(dǎo)入這一個(gè)Common. xcconfig的文件缸榄,這就實(shí)現(xiàn)了不同環(huán)境下動(dòng)態(tài)的配置,不同環(huán)境下的預(yù)編譯宏名一樣只是值會(huì)不一樣祝拯,而且這些xcconfig文件可以在不同的項(xiàng)目中使用甚带。
這樣就可以簡(jiǎn)單的理解為Common. xcconfig實(shí)現(xiàn)了一個(gè)Build Setting里面的一個(gè)方法,而其他的xcconfig文件調(diào)用這個(gè)方法進(jìn)行具體設(shè)置佳头。
上面在Preprocessor Macros中配置的用于在代碼中區(qū)分不同環(huán)境的預(yù)編譯宏鹰贵,也可以直接在Common. xcconfig中設(shè)置,只是在代碼中進(jìn)行區(qū)分就要區(qū)分不同宏的值了畜晰。
2.其他xcconfig代碼:
#include "Common.xcconfig"
VariableA = @"UAT_α.xcconfig_VariableA"
VariableB = @"UAT_α.xcconfig_VariableB"
3砾莱、將xcconfig與環(huán)境進(jìn)行關(guān)聯(lián):
我們來(lái)到工程下的info->Configuration瑞筐,
我們發(fā)現(xiàn)凄鼻,每一種環(huán)境下都有兩個(gè)這樣的設(shè)置,一個(gè)設(shè)置是工程的xcconfig文件配置聚假,另一個(gè)則是target的xcconfig文件配置块蚌,在這里配置xcconfig意味著APP在運(yùn)行的時(shí)候會(huì)去加載相應(yīng)xcconfig中的設(shè)置。上面我們說(shuō)到了配置的繼承關(guān)系膘格,那么這里只設(shè)置target的xcconfig就夠了峭范,而且你設(shè)置了工程的xcconfig就相當(dāng)于在編譯的時(shí)候?qū)⑦@些xcconfig的配置加載設(shè)置了兩遍!其實(shí)你也會(huì)發(fā)現(xiàn)此時(shí)再設(shè)置工程的xcconfig也沒有關(guān)系瘪贱。這里我暫且只設(shè)置UAT_α和UAT_β環(huán)境下的xcconfig纱控,Release環(huán)境留著調(diào)式pod辆毡。
2019-6-7更新:
經(jīng)過(guò)上面的設(shè)置,在某些Xcode上會(huì)出現(xiàn)“use undecalred indentifire”的錯(cuò)誤甜害,經(jīng)過(guò)不斷嘗試后發(fā)現(xiàn)舶掖,將工程的xcconfig文件對(duì)應(yīng)為Commn就可以了,猜測(cè)與Xcode自身有關(guān)尔店,配置文件的加載順序會(huì)影響到代碼的編譯眨攘。
接下來(lái)你就可以直接在代碼中使用VariableA、VariableB宏了:
// 這里并不能在Release環(huán)境下使用這些宏嚣州,否則會(huì)報(bào)錯(cuò)鲫售。
NSLog(@"%@ - %@",VariableA, VariableB);
// ConfigDemo_UAT_α、ConfigDemo_UAT_β環(huán)境打印結(jié)果分別為
// UAT_α.xcconfig_VariableA - UAT_α.xcconfig_VariableB
// UAT_β.xcconfig_VariableA - UAT_β.xcconfig_VariableB
Pod調(diào)試该肴,Pod安裝SDWebImage
在刪除上面的log代碼之后情竹,你會(huì)發(fā)現(xiàn)只有在Release環(huán)境下能夠運(yùn)行!首先我們來(lái)看看報(bào)錯(cuò):
是的匀哄,工程找不到相關(guān)文件了鲤妥,其實(shí)這個(gè)你在終端的提示中就可以發(fā)現(xiàn)端倪:
大概意思是你需要你配置的xcconfig文件中導(dǎo)入pod配置文件的路徑。
在完成一次pod install之后拱雏,Pods工程會(huì)為每一個(gè)環(huán)境生成一個(gè)xcconfig文件棉安,包括默認(rèn)的debug環(huán)境,如果我們的目標(biāo)工程ConfigDemo對(duì)應(yīng)的環(huán)境沒有配置xcconfig文件铸抑,那么就會(huì)在ConfigDemo工程下拷貝一份對(duì)應(yīng)的xcconfig文件并自動(dòng)在環(huán)境中完成配置贡耽,這種配置讓工程能夠使用pod。大家可以看到這里在ConfigDemo工程下只有Release. xcconfig文件的拷貝鹊汛,而此時(shí)Release環(huán)境下的Configuration配置已經(jīng)發(fā)生了改變蒲赂。
我們只需要在其他xcconfig文件中導(dǎo)入相關(guān)的pod下的xcconfig就好了,記得使用相對(duì)路徑刁憋,否則在其他電腦上就不能運(yùn)行了:
#include "Pods/Target Support Files/Pods-ConfigDemo/Pods-ConfigDemo.release.xcconfig"
這個(gè)時(shí)候你就可以刪除在ConfigDemo工程下的.release.xcconfig文件滥嘴,并去Configuration中配置你自己的xcconfig文件了,記得重新pod install一下至耻。
Demo:https://github.com/Randy1993/ConfigDemo
宏DEBUG丟失的問(wèn)題
上述的配置結(jié)束之后若皱,會(huì)導(dǎo)致Pod工程下UAT_α等缺少DEBUG宏,導(dǎo)致某些三方庫(kù)無(wú)法正常使用尘颓,比如說(shuō)MLeaksFinder
無(wú)效走触。在Podfile中添加如下代碼即可:
pod 'MLeaksFinder'
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
if target.name == 'MLeaksFinder'
target.build_configurations.each do |config|
if config.name == 'UAT_α'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)','DEBUG=1']
end
end
end
end
end
參考文章:
http://www.reibang.com/p/83b6e781eb51
http://liumh.com/2016/05/22/use-xcconfig-config-specific-variable/#xcconfig-environment 關(guān)于xcconfig文件的說(shuō)明。
http://www.reibang.com/p/51a2bbe877aa Configuration配置