Xcode多環(huán)境配置

Xcode多環(huán)境配置一共有3種形式:

  • Target
  • Scheme
  • xcconfig

Project:包含了項(xiàng)目所有的代碼、資源文件、所有信息。(一個(gè)項(xiàng)目是多個(gè)project的集合)
Target:對指定代碼和資源文件的具體構(gòu)建方式。(指定某些代碼如何生成ipa包,類似打工人的角色)
Scheme:對指定Target的環(huán)境配置。(配置編譯環(huán)境變量)
這也就是我們修改一些配置的時(shí)候需要選中Target再去修改的原因。

多Target配置

在項(xiàng)目中選中Target復(fù)制就生成新的Target了。

image.png

在這里復(fù)制后并沒有產(chǎn)生額外代碼,只是復(fù)制了一個(gè)新的構(gòu)建模式。
image.png

相當(dāng)于可以直接分別配置Info.plist文件,在Target中修改bundleId后就相當(dāng)于兩個(gè)Target是兩個(gè)App了。
同時(shí)可以在Preprocessor Macros中配置一些宏定義用于代碼中區(qū)分Target
image.png

比如在OCSwift混編的時(shí)候,在OC中導(dǎo)入頭文件就可以用這個(gè)宏來處理:

#if DEV
#import "TestMutableConfig_dev-Swift.h"
#else
#import "TestMutableConfig-Swift.h"
#endif

對應(yīng)的Swift文件:

image.png

Swift中也可以用Swift宏來處理:
Other Swift Flags中配置變量- D DEV(空格有沒有都行)
image.png

#if DEV
func log(message: String) {
    print(message)
}
#endif
?  ~  swiftc --help | grep -- '-D'
-D <value>              Marks a conditional compilation flag as true

Target方式配置多環(huán)境
1.會生成多個(gè)Info.plist文件;
2.配置比較繁瑣,需要同步配置容易混亂
那么對于多Target的場景是可以在Build Phases中控制要編譯的文件和資源。

image.png

多scheme配置

scheme默認(rèn)有DebugReleaseconfig我們可以按需添加。在Target中添加變量的時(shí)候已經(jīng)用到過了。
配置在Project -> Info -> Configurations

image.png

比如我們有appStore包,有企業(yè)包。那么各復(fù)制一份對應(yīng)的DebugRelease(最好是配置完成后再復(fù)制)
image.png

運(yùn)行/打包的時(shí)候選擇對應(yīng)的Scheme就可以了。
image.png

這種情況下運(yùn)行不同配置的時(shí)候需要來回切換。
可以通過創(chuàng)建Scheme對應(yīng)不同config
image.png

image.png

這個(gè)時(shí)候只需要切換Scheme運(yùn)行就可以了。
image.png

比如我們上傳打包ipa的時(shí)候,有時(shí)候會錯(cuò)將debug模式下的包上傳上去,尤其是在發(fā)灰度包的時(shí)候。這里有兩個(gè)方案:
1.通過config配置。
2.打包的時(shí)候通過腳本修改info.plist文件增加一個(gè)變量。

release包賦值為0debug包賦值為1。這樣在上傳ipa包的時(shí)候后端讀取Info.plist做判斷,debug包直接報(bào)錯(cuò)不讓傳。
這里實(shí)現(xiàn)以下方式1:
Targets -> Build Settings -> + -> Add User-Defined Setting

image.png

添加一個(gè)IPAFLAGrelease模式下是1debug模式下是0:
image.png

Info.plist文件中增加配置:
image.png

到這里就完成了

  • User-Defined添加配置;
  • Info.plist暴露配置的目的。

在代碼中測試下:

    NSString *infoPath = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"];
    NSDictionary *infoDic = [[NSDictionary alloc] initWithContentsOfFile:infoPath];
    NSLog(@"IPAFLAG = %@",infoDic[@"IPAFLAG"]);

Debug下:

 IPAFLAG = 1

當(dāng)然也可以配置app圖標(biāo):
Assets.xcassets中添加不同的資源文件

image.png

Scheme還可以控制傳遞參數(shù)等,一般不常用。

image.png

Scheme情況只需要在一個(gè)build setting中就能完成配置了,比多Target方便好維護(hù)。
缺點(diǎn)是還需要在build setting中設(shè)置。

xcconfig

這個(gè)我們平時(shí)都接觸到了,可能好多人沒有注意到,用的最廣泛的就是cocoapods
比如Other Linker FlagsSearch Paths

image.png

image.png

那么Cocoapods是怎么配置的呢?
image.png

就是使用xcconfig配置的:

FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

xcconfigkey-value的形式配置的。那么怎么對應(yīng)到xcconfig文件的呢?

image.png

Configurations中對應(yīng)配置的。

配置自己的xcconfig文件

新建 -> Configuration Settings File

image.png

命令規(guī)則為:以所在目錄開頭-工程名稱.config名稱/環(huán)境名稱,比如Config-TestMutableConfig.Debug
image.png

接著可以在config中選擇配置
image.png

  • 1中設(shè)置是對整個(gè)Project生效。
  • 2中設(shè)置是對Target生效。

還是以IPAFLAG為例,以xcconfig的方式配置。
plist中的配置不變,User-Defined配置刪除

    <key>IPAFLAG</key>
    <string>${IPAFLAG}</string>

Config-TestMutableConfig.Debug.xcconfig

IPAFLAG = 1

Config-TestMutableConfig.Release.xcconfig

IPAFLAG = 0

代碼中讀取下:

    NSString *infoPath = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"];
    NSDictionary *infoDic = [[NSDictionary alloc] initWithContentsOfFile:infoPath];
    NSLog(@"IPAFLAG = %@",infoDic[@"IPAFLAG"]);
IPAFLAG = 1

這樣配置更清晰,便于管理。

xcconfig其它用途

處了配置變量還可以配置Build Setting中的配置:

IPAFLAG = 1
//ld
OTHER_LDFLAGS = -framework "AFNetworking"

image.png

編譯后雖然報(bào)錯(cuò)但是已經(jīng)配置進(jìn)來了。那么Build Setting中的配置都可以用xcconfig文件來管理了。
OTHER_LDFLAGSbuild setting中的縮寫,本質(zhì)是key-value。具體的key可以在xcodebuildsettings中查找。
image.png

image.png

IPAFLAG = 1

//ld配置連接器
//OTHER_LDFLAGS為build中的縮寫
OTHER_LDFLAGS = -framework "AFNetworking"

HEADER_SEARCH_PATHS = /usr/info

image.png

可以看到編譯后就配置進(jìn)去了。所以通過xcconfig文件就完成了多環(huán)境配置的場景。

所以xcconfig配合scheme以及config就完成了項(xiàng)目的多環(huán)境配置。并且xcconfig可以直接復(fù)制到其它項(xiàng)目復(fù)用。

沖突解決

前面說過cocoapods會創(chuàng)建xcconfig文件,在上面的例子中就和自己創(chuàng)建的沖突了。因?yàn)?code>Configurations中只能指定一個(gè)。
當(dāng)然Cocoapods安裝的時(shí)候不會覆蓋我們在Configurations配置的。

image.png

可以看到在pod install的時(shí)候Cocoapods給警告了:

[!] CocoaPods did not set the base configuration of your project 
because your project already has a custom config set. 
In order for CocoaPods integration to work at all, please either set the base configurations of the target `TestMutableConfig` to `Target Support Files/Pods-TestMutableConfig/Pods-TestMutableConfig.debug.xcconfig` 
or include the `Target Support Files/Pods-TestMutableConfig/
Pods-TestMutableConfig.debug.xcconfig` in your build configuration 
(`TestMutableConfig/Config/Config-TestMutableConfig.Debug.xcconfig`).

在這里已經(jīng)給提示讓我們導(dǎo)入了。

#include "Target Support Files/Pods-TestMutableConfig/Pods-TestMutableConfig.debug.xcconfig"

導(dǎo)入后依然報(bào)錯(cuò):

image.png

找不到目錄,查看文件位置發(fā)現(xiàn)少了Pods/加上后編譯成功

#include "Pods/Target Support Files/Pods-TestMutableConfig/Pods-TestMutableConfig.debug.xcconfig"
IPAFLAG = 1

//ld配置連接器
//OTHER_LDFLAGS為build中的縮寫
OTHER_LDFLAGS = -framework "AFNetworking"

再次pod install就沒有警告了

image.png

那么還存在一個(gè)問題,自己配制的xcconfigcocoapods生成的xcconfig如果有相同變量會怎么樣?比如上面的OTHER_LDFLAGS
可以看到生效的是自己配置的。
image.png

cocoapods的配置中有一個(gè)繼承$(inherited),這里的繼承實(shí)際上是兩個(gè)字符串拼接起來。
image.png

所以自己配制的也加上$(inherited)

#include "Pods/Target Support Files/Pods-TestMutableConfig/Pods-TestMutableConfig.debug.xcconfig"
IPAFLAG = 1

//ld配置連接器
//OTHER_LDFLAGS為build中的縮寫
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking"

可以看到繼承過來了


image.png

代碼中調(diào)用下:


image.png

編譯成功。

推薦使用scheme + xcconfig配置管理項(xiàng)目環(huán)境。當(dāng)然在build setting中設(shè)置的并不會被覆蓋(不同名,同名可以繼承,如果是值key相同會覆蓋后面有總結(jié)優(yōu)先級)

xcconfig配置總結(jié)

key-value 組成

配置文件由一系列鍵值分配組成:

BUILD_SETTING_NAME = value

注釋

xcconfig文件只有一種注釋方式//

//

那么這里就有一個(gè)問題了,如果我們要配置一個(gè)域名該怎么辦呢?比如:

HOST_URL = https://127.0.0.1

可以通過中間值解決:

TEMP=/
HOST_URL = https:${TEMP}/127.0.0.1

include導(dǎo)入其他設(shè)置

可以通過include關(guān)鍵字導(dǎo)入其他的xcconfig內(nèi)的配置。通過include關(guān)鍵字后接上雙引號:

#include "Other.xcconfig"

在引入的文件時(shí),如果是以/開頭,代表絕對路徑:

#include "/Users/zaizai/Desktop/TestMutableConfig/Pods/Target Support Files/Pods-TestMutableConfig/Pods-TestMutableConfig.debug.xcconfig"

相對路徑,以${SRCROOT}路徑為開始:

#include "Pods/Target Support Files/Pods-TestMutableConfig/Pods-TestMutableConfig.debug.xcconfig"

變量

變量定義,按照OC命名規(guī)則,僅由大寫字母,數(shù)字和下劃線_組成,原則上大寫,也可以不。字符串可以是"也可以是'號。

  1. xcconfig中定義的變量與Build Settings的一致,會發(fā)生覆蓋。可以通過$(inherited)讓當(dāng)前變量繼承變量原有值。(當(dāng)然對于系統(tǒng)的key最好都加上$(inherited)`)
//A config
OTHER_LDFLAGS = -framework SDWebImage
//B config
OTHER_LDFLAGS = $(inherited) -framework AFNetworking
//build setting中
// OTHER_LDFLAGS = -framework SDWebImage -framework AFNetworking

??:有部分變量不能通過xcconfig配置到Build Settings中。如:配置PRODUCT_BUNDLE_IDENTIFIER不起作用。

  1. 引用變量,$()${}兩種寫法都可以
VALUE=HotpotCat

KEY1=$(VALUE)
KEY2=${VALUE}
  1. 條件變量,根據(jù)SDKArchConfigration對設(shè)置進(jìn)行條件化:
// 指定`Configration`是`Debug`
// 指定`SDK`是模擬器,還有iphoneos*、macosx*等
// 指定生效架構(gòu)為`x86_64`
OTHER_LDFLAGS[config=Debug][sdk=iphonesimulator*][arch=x86_64]= $(inherited) -framework "HotpotCat"

??:在Xcode 11.4及以后版本,可以使用default來指定變量為空時(shí)的默認(rèn)值。

$(BUILD_SETTING_NAME:default=value)

優(yōu)先級(高->低)

  • 手動(dòng)配置Target Build Settings;
  • Target中配置的xcconfig文件;
  • 手動(dòng)配置Project Build Settings;
  • Project中配置的xcconfig文件。

資料

xcodebuildsettings

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

推薦閱讀更多精彩內(nèi)容