這里我們會(huì)介紹三種,在充分了解前兩種的基礎(chǔ)上,建議大家在開(kāi)發(fā)中靈活使用第三種方法。當(dāng)然,大家在熟練的情況也可以根據(jù)實(shí)際情況自己組合使用
在講解多環(huán)境配置之前我們先來(lái)認(rèn)識(shí)一下,我們?cè)赬code常見(jiàn)的一些名詞,都代表什么意思?
-
Project:包含了項(xiàng)目所有的代碼,資源文件,所有信息。 -
Target:對(duì)指定代碼和資源文件的具體構(gòu)建方式。 -
Scheme:對(duì)指定Target的環(huán)境配置。
首先我們來(lái)看一個(gè)熟悉的東西:
image.png
相信大家都會(huì)通多上面修改Configuration的方式來(lái)切換Debug和Release的開(kāi)發(fā)環(huán)境。但是僅僅是這樣并不能滿足我們?nèi)粘5拈_(kāi)發(fā)需求,下面我們來(lái)介紹三種Xcode的多環(huán)境配置,希望可以在日常的開(kāi)發(fā)中給大家?guī)?lái)方便,增加效率。
方法一:通過(guò)增加Target
我們知道,Target是對(duì)指定代碼和資源文件的具體構(gòu)建方式。那么理論上我們知道復(fù)制一份Target出來(lái),然后在不同的Target下,設(shè)置不同的參數(shù)配置不就可以了嗎!
下面我們來(lái)配置一下:
1、首先我們針對(duì)對(duì)應(yīng)的Target,制作一個(gè)副本

2、制作完成之后,我們會(huì)發(fā)現(xiàn)工程里面多了一個(gè)
Target和一個(gè)Info.plist文件,同時(shí)也會(huì)多一個(gè)Scheme。

3、我們可以通過(guò)修改Bundle Indentifier、Info.plist和Scheme名稱來(lái)進(jìn)行區(qū)分


?? 注意,修改外Info.plist文件名之后,一定要在對(duì)應(yīng)的Build Settings里面修改Info.plist路徑

- 我們接著講一下,
Target中預(yù)定義宏的的設(shè)置
我們?cè)?code>testDebug中設(shè)置自定義的宏:
image.png
使用如下:
if (TEST_DEBUG) {
NSLog(@"Debug");
} else {
NSLog(@"Release");
}
注意 ?? :此時(shí)TEST_DEBUG我們并不能在test中使用,因?yàn)槲覀冎辉?code>testDebug設(shè)置了;那么當(dāng)我們切換到test環(huán)境中的時(shí)候,就會(huì)報(bào)錯(cuò):(這里要注意,對(duì)個(gè)Target操作的只有一套代碼)

這時(shí)候我們只需要在
test環(huán)境下也設(shè)置同樣名字的宏就可以了,宏對(duì)應(yīng)的值設(shè)置成不同的,就可以在代碼里面區(qū)分不同的環(huán)境,執(zhí)行不同的指令了。
-
Swift環(huán)境中設(shè)置
Other Swift Flags,混編情況下也是一樣。
我們?cè)谏厦婀こ痰幕A(chǔ)上看下混編要怎么設(shè)置(注意,視情況做出調(diào)整):
這里要注意,在添加宏一定要在前面加一個(gè)-D
image.png
方法二:添加Scheme

然后我們可以對(duì)不同的
Scheme配置不同的configuration來(lái)進(jìn)行環(huán)境區(qū)分。如下:

這樣我們就可以通過(guò)切換不同的
Scheme來(lái)切換不同的開(kāi)發(fā)環(huán)境。
-
舉個(gè)例子,不同的
Scheme對(duì)應(yīng)不同的AppIcon:
首先我們要在Assets.xcassets再添加一個(gè)AppIcon:
image.png
接著我們可以在target的Build Settings里面設(shè)置不同的configuration對(duì)應(yīng)不同的AppIcon:
image.png -
我們還可以針對(duì)不同
Scheme設(shè)置不同的App Name:
在Target的Build Settings里面添加自定義的字段,如下:
image.png
假設(shè)我們現(xiàn)在就將字段名定義為BUNDLEDISPLAY_NAME,然后Debug模式下就叫Debug,Release模式下就叫Release。
接著我們要在Info.plist文件中替換Bundle name:
image.png
效果如下:
debug.png

缺點(diǎn):此時(shí)同樣的,我們還是需要在
Target里面修改很多東西,這樣的還難免會(huì)遺漏一些東西,改起來(lái)也不是特別的方便。
方法三:利用xcconfig文件,結(jié)合自定義的Scheme來(lái)配置多環(huán)境開(kāi)發(fā)
- 首先我們來(lái)了解一下什么是
xcconfig文件,我們?cè)谑褂?code>cocopod的時(shí)候,會(huì)自動(dòng)什么pod的xcconfig文件,如下:
image.png
其實(shí)這個(gè)xcconfig文件類似于plist文件,就是一個(gè)Key-Value的集合,其對(duì)應(yīng)的就是Target中的設(shè)置:
image.png - 既然
cocopod可以定義自己的xcconfig文件,那么我們也可以定義自己的xcconfig文件,這樣做的好處是,將需要修改的環(huán)境變量集中到一個(gè)文件里面,這樣便于管理。
下面我們自定義自己的xcconfig文件:
image.png - ?? 注意:
xcconfig文件的命名規(guī)則是:<文件夾名稱-APP名稱.對(duì)應(yīng)的configuration>如下:
image.png - 然后我們?cè)?code>PROJECT-
Info-Configurations里面,將不同的configuration設(shè)置對(duì)應(yīng)的xcconfig文件:
image.png -
xcconfig文件其實(shí)就是一個(gè)Key-Value文件,對(duì)應(yīng)的就是Target的設(shè)置。下面我們來(lái)測(cè)試一下:
1、首先我們?cè)?code>Target的Build Settings里面設(shè)置自己的字段:
image.png
2、接著我們給工程加一個(gè)test1_Debug的Scheme,對(duì)應(yīng)的就是Debug模式;原來(lái)的test1對(duì)應(yīng)Release模式:
image.png
3、根據(jù)上面講的,將不同的configuration設(shè)置對(duì)應(yīng)的xcconfig文件,在xcconfig文件中我們這樣寫:
Debug文件:APP_CONFIG = APP_Debug_Replace
Release文件:APP_CONFIG = APP_Release_Replace
4、我們?cè)?code>Info.plist文件中添加一個(gè)剛剛設(shè)置的字段:
image.png
5、打印我們自定義的字段:
NSString *path = [NSBundle.mainBundle pathForResource:@"Info" ofType:@"plist"];
NSDictionary *infoDic = [[NSDictionary alloc] initWithContentsOfFile:path];
NSLog(@"%@",infoDic[@"APP_CONFIG"]);
/*運(yùn)行test1*/
輸出結(jié)果:APP_Release_Replace
/*運(yùn)行test1_Debug*/
輸出結(jié)果:APP_Debug_Replace
講到這里,大家可能會(huì)覺(jué)得第三種方法中,單獨(dú)添加一個(gè)test1_Debug完全就是多余,可以通過(guò)運(yùn)行的時(shí)候切換test1的configuration也能實(shí)現(xiàn)上面的效果。
這里請(qǐng)大家考慮一下,實(shí)際的開(kāi)發(fā)中,你面對(duì)的可能不只是Debug & Release環(huán)境,可能有本地、測(cè)試服、正式服等等。因此個(gè)人建議,用不同的Scheme區(qū)分開(kāi),是比較高效的處理方式。
這里給大家推薦一個(gè)網(wǎng)站,可以查到Target的各個(gè)字段對(duì)應(yīng)的縮寫:Xcode Build Settings
- 下面我們介紹一下最后一個(gè)知識(shí)點(diǎn):xcconfig文件沖突
- 沖突 1:
實(shí)際開(kāi)發(fā)中,我們會(huì)使用Cocopods來(lái)管理我們的第三方庫(kù),Cocopods也會(huì)給我們生成一些xcconfig文件(這里注意?? :每次pod,Cocopods都會(huì)從新生成xcconfig文件,所以不要在Cocopods生成的xcconfig文件中做修改)
那么這個(gè)時(shí)候,就有一個(gè)問(wèn)題,我們針對(duì)configuration到底要選哪一個(gè)xcconfig文件呢?
答案當(dāng)然是我們自定義的xcconfig
這樣有衍生出另一問(wèn)題,那么pod生成的xcconfig我們?cè)撛趺刺幚?,如果不添加,則pod install就會(huì)出問(wèn)題,如果是之前pod好的工程,那么pod中針對(duì)Target的一些設(shè)置又該怎么辦?
其實(shí)很簡(jiǎn)單,我們只需要在自定義xcconfig文件中引入pod生成的xcconfig文件就可以了,如下:
#include "Pods/Target Support Files/Pods-test1/Pods-test1.debug.xcconfig"
- 沖突 2:
解決了上面的問(wèn)題,我們來(lái)看另一問(wèn)題,嚴(yán)格將問(wèn)題2也是一個(gè)衍生問(wèn)題。
如果自定義xcconfig 和 pod生成的xcconfig文件,對(duì)同一個(gè)字段進(jìn)行了修改,那Xcode會(huì)用哪個(gè)文件中的配置呢?
答案是:自定義xcconfig,其實(shí)大家想一下就明白了,自定義的 引用 pod生成的,然后Xcode再引用自定義的。
那么像這種問(wèn)題我們?cè)撛趺唇鉀Q呢?
這里我們先給出答案:使用$(inherited),可以理解為繼承。
下面我們看一下具體的使用場(chǎng)景:
首先我們?cè)谧远x的xcconfig文件中添加
OTHER_LDFLAGS = -framework "SDWebImage"
同時(shí)我們也pod了AFNetworking。
此時(shí)我們會(huì)發(fā)現(xiàn),在Target的Build Settings-Other Link Flags路面只有SDWebImage,如下:

這也就意味著,我們引入的第三方庫(kù)的鏈接是失敗的。
這時(shí)候,我們就可以在等號(hào)加上
-framework "SDWebImage":
OTHER_LDFLAGS = $(inherited) -framework "SDWebImage"
這里跟大家分享一下:?jiǎn)栴} 2 的解決辦法,其實(shí)就在pod自己生成的xcconfig里面,如果有興趣可以先不自定義xcconfig,使用pod引入一個(gè)三方庫(kù),看看pod自動(dòng)生成的xcconfig是怎么寫的,然后對(duì)應(yīng)的Target里面的設(shè)置又有了哪些變化。
Tips:
大家在配置自己的xcconfig文件的時(shí)候有幾個(gè)小技巧跟大家講一下:
- 1、在
Build Settings里面自定義了URL字段,在xcconfig如何配置//的問(wèn)題
如果我們直接在xcconfig文件中寫上對(duì)應(yīng)的URL會(huì)是被識(shí)別為注釋符號(hào)
我們可以先定義一個(gè)/的變量:
A = /
HOST_URL = ${A}/192.168.1.1
其中${A} 和 $(A) 是等價(jià)的。
- 2、比如說(shuō)我們現(xiàn)在要配置
OTHER_LDFLAGS,按照上面講的我們是這樣寫的:
OTHER_LDFLAGS = -framework "SDWebImage"
其實(shí)我們還可以添加附加條件,比如:指定特定的開(kāi)發(fā)環(huán)境、機(jī)型、架構(gòu)等等,如下:
OTHER_LDFLAGS[config=Debug][sdk=iphonesimulator*][arch=x86_64] = -framework "SDWebImage"
此時(shí)OTHER_LDFLAGS引入SDWebImage只會(huì)在Debug模式下,運(yùn)行模擬器并且對(duì)應(yīng)的執(zhí)行架構(gòu)為x86_64的時(shí)候,才會(huì)執(zhí)行。
優(yōu)先級(jí)(由高到低):
- 手動(dòng)配置Target Build Settings
- Target中配置的xcconfig文件
- 手動(dòng)配置Project Build Settings
- Project中配置的xcconfig文件















