Xcode多環(huán)境配置一共有3種形式:
- Target
- Scheme
- xcconfig
Project:包含了項目所有的代碼购笆、資源文件同欠、所有信息行您。(一個項目是多個project的集合)
Target:對指定代碼和資源文件的具體構(gòu)建方式娃循。(指定某些代碼如何生成ipa
包捌斧,類似打工人的角色)
Scheme:對指定Target的環(huán)境配置。(配置編譯環(huán)境變量)
這也就是我們修改一些配置的時候需要選中Target
再去修改的原因姓迅。
多Target配置
在項目中選中Target
復(fù)制就生成新的Target
了丁存。
在這里復(fù)制后并沒有產(chǎn)生額外代碼解寝,只是復(fù)制了一個新的構(gòu)建模式聋伦。
相當(dāng)于可以直接分別配置
Info.plist
文件兵拢,在Target
中修改bundleId
后就相當(dāng)于兩個Target
是兩個App
了说铃。同時可以在
Preprocessor Macros
中配置一些宏定義用于代碼中區(qū)分Target
截汪。比如在
OC
和Swift
混編的時候,在OC
中導(dǎo)入頭文件就可以用這個宏來處理:
#if DEV
#import "TestMutableConfig_dev-Swift.h"
#else
#import "TestMutableConfig-Swift.h"
#endif
對應(yīng)的Swift
文件:
在
Swift
中也可以用Swift
宏來處理:在
Other Swift Flags
中配置變量- D DEV
(空格有沒有都行)#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.會生成多個Info.plist
文件;
2.配置比較繁瑣暑椰,需要同步配置容易混亂
那么對于多Target
的場景是可以在Build Phases
中控制要編譯的文件和資源一汽。
多scheme配置
scheme
默認(rèn)有Debug
和Release
的config
我們可以按需添加。在Target
中添加變量的時候已經(jīng)用到過了监憎。
配置在Project -> Info -> Configurations
中
比如我們有appStore包,有企業(yè)包褐筛。那么各復(fù)制一份對應(yīng)的
Debug
和Release
(最好是配置完成后再復(fù)制)運行/打包的時候選擇對應(yīng)的
Scheme
就可以了。這種情況下運行不同配置的時候需要來回切換笤虫。
可以通過創(chuàng)建
Scheme
對應(yīng)不同config
:這個時候只需要切換
Scheme
運行就可以了。比如我們上傳打包
ipa
的時候,有時候會錯將debug
模式下的包上傳上去榨了,尤其是在發(fā)灰度包的時候龙屉。這里有兩個方案:1.通過
config
配置转捕。2.打包的時候通過腳本修改
info.plist
文件增加一個變量瓜富。
release
包賦值為0
与柑,debug
包賦值為1
价捧。這樣在上傳ipa
包的時候后端讀取Info.plist
做判斷结蟋,debug
包直接報錯不讓傳嵌屎。
這里實現(xiàn)以下方式1:
Targets -> Build Settings -> + -> Add User-Defined Setting
:
添加一個
IPAFLAG
植榕,release
模式下是1
尊残,debug
模式下是0
:Info.plist
文件中增加配置:到這里就完成了
-
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
中添加不同的資源文件
Scheme
還可以控制傳遞參數(shù)等事富,一般不常用统台。
多Scheme
情況只需要在一個build setting
中就能完成配置了,比多Target
方便好維護贵扰。
缺點是還需要在build setting
中設(shè)置戚绕。
xcconfig
這個我們平時都接觸到了舞丛,可能好多人沒有注意到球切,用的最廣泛的就是cocoapods
吨凑。
比如Other Linker Flags
鸵钝、Search Paths
蒋伦。
那么
Cocoapods
是怎么配置的呢?就是使用
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
xcconfig
是key-value
的形式配置的。那么怎么對應(yīng)到xcconfig
文件的呢?
在
Configurations
中對應(yīng)配置的申屹。
配置自己的xcconfig
文件
新建 -> Configuration Settings File
命令規(guī)則為:
以所在目錄開頭-工程名稱.config名稱/環(huán)境名稱
,比如Config-TestMutableConfig.Debug
接著可以在
config
中選擇配置-
1
中設(shè)置是對整個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"
編譯后雖然報錯但是已經(jīng)配置進來了闷袒。那么
Build Setting
中的配置都可以用xcconfig
文件來管理了囊骤。OTHER_LDFLAGS
為build setting
中的縮寫也物,本質(zhì)是key-value
滑蚯。具體的key
可以在xcodebuildsettings中查找告材。IPAFLAG = 1
//ld配置連接器
//OTHER_LDFLAGS為build中的縮寫
OTHER_LDFLAGS = -framework "AFNetworking"
HEADER_SEARCH_PATHS = /usr/info
可以看到編譯后就配置進去了绢慢。所以通過
xcconfig
文件就完成了多環(huán)境配置的場景胰舆。
所以xcconfig
配合scheme
以及config
就完成了項目的多環(huán)境配置缚窿。并且xcconfig
可以直接復(fù)制到其它項目復(fù)用倦零。
沖突解決
前面說過cocoapods
會創(chuàng)建xcconfig
文件扫茅,在上面的例子中就和自己創(chuàng)建的沖突了葫隙。因為Configurations
中只能指定一個。
當(dāng)然Cocoapods
安裝的時候不會覆蓋我們在Configurations
配置的焰手。
可以看到在
pod install
的時候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)入后依然報錯:
找不到目錄怀喉,查看文件位置發(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
就沒有警告了
那么還存在一個問題书妻,自己配制的
xcconfig
和cocoapods
生成的xcconfig
如果有相同變量會怎么樣?比如上面的OTHER_LDFLAGS
躬拢。可以看到生效的是自己配置的躲履。
cocoapods
的配置中有一個繼承$(inherited)
估灿,這里的繼承實際上是兩個字符串拼接起來崇呵。所以自己配制的也加上
$(inherited)
#include "Pods/Target Support Files/Pods-TestMutableConfig/Pods-TestMutableConfig.debug.xcconfig"
IPAFLAG = 1
//ld配置連接器
//OTHER_LDFLAGS為build中的縮寫
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking"
可以看到繼承過來了
代碼中調(diào)用下:
編譯成功。
推薦使用scheme + xcconfig
配置管理項目環(huán)境馅袁。當(dāng)然在build setting
中設(shè)置的并不會被覆蓋(不同名,同名可以繼承荒辕,如果是值key相同會覆蓋后面有總結(jié)優(yōu)先級)
xcconfig配置總結(jié)
key-value 組成
配置文件由一系列鍵值分配組成:
BUILD_SETTING_NAME = value
注釋
xcconfig文件只有一種注釋方式//
//
那么這里就有一個問題了汗销,如果我們要配置一個域名該怎么辦呢?比如:
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"
在引入的文件時弛针,如果是以/
開頭,代表絕對路徑:
#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ù)字和下劃線_
組成茧跋,原則上大寫,也可以不卓囚。字符串可以是"
也可以是'
號瘾杭。
- 在
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
不起作用讨阻。
- 引用變量,
$()
和${}
兩種寫法都可以
VALUE=HotpotCat
KEY1=$(VALUE)
KEY2=${VALUE}
- 條件變量篡殷,根據(jù)
SDK
钝吮、Arch
和Configration
對設(shè)置進行條件化:
// 指定`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
來指定變量為空時的默認(rèn)值飞袋。
$(BUILD_SETTING_NAME:default=value)
優(yōu)先級(高->低)
- 手動配置
Target Build Settings
; -
Target
中配置的xcconfig
文件; - 手動配置
Project Build Settings
; -
Project
中配置的xcconfig
文件。