手把手教你給一個(gè)iOS app配置多個(gè)環(huán)境變量

前言

談到多環(huán)境悼潭,相信現(xiàn)在大多公司都至少有2-3個(gè)app環(huán)境了攘乒,比如Test環(huán)境设预,UAT(User Acceptance Test)用戶驗(yàn)收測(cè)試環(huán)境脐彩,Release環(huán)境等等碎乃。當(dāng)需要開(kāi)發(fā)打多個(gè)包的時(shí)候,一般常見(jiàn)做法就是直接代碼里面修改環(huán)境變量惠奸,改完之后Archive一下就打包了梅誓。當(dāng)然這種做法很正確,只不過(guò)不是很優(yōu)雅很高效佛南。如果搭建好了Jenkins(搭建教程)梗掰,我們利用它來(lái)優(yōu)雅的打包。如果利用Jenkins來(lái)打包嗅回,我們就需要來(lái)給app來(lái)配置一下多個(gè)環(huán)境變量了愧怜。之后Jenkins分別再不同環(huán)境下自動(dòng)集成即可。接下來(lái)妈拌,我們來(lái)談?wù)劤R?jiàn)的2種做法拥坛。

目錄

  • 1.利用Build Configuration來(lái)配置多環(huán)境
  • 2.利用xcconfig文件來(lái)配置多環(huán)境
  • 3.利用Targets來(lái)配置多環(huán)境

一.利用Build Configuration來(lái)配置多環(huán)境

前言里面我們先談到了需求,由于需要配置多個(gè)環(huán)境尘分,并且多個(gè)環(huán)境都需要安裝到手機(jī)上猜惋,那么可以配置Build Configuration來(lái)完成這個(gè)任務(wù)。如果Build Configuration還不熟悉的培愁,可以先溫習(xí)一下官方文檔著摔,新版文檔鏈接在這里Build settings reference

1. 新建Build Configuration

先點(diǎn)擊Project里面找到Configuration定续,然后選擇添加谍咆,這里新加一個(gè)Configuration。系統(tǒng)默認(rèn)是2個(gè)私股,一個(gè)Debug摹察,一個(gè)Release。這里我們需要選擇是復(fù)制一個(gè)Debug還是Release倡鲸。Release和Debug的區(qū)別是供嚎,Release是不能調(diào)試程序,因?yàn)槟J(rèn)是屏蔽了可調(diào)試的一些參數(shù),具體可以看BuildSetting里面的區(qū)別克滴,而且Release編譯時(shí)有做編譯優(yōu)化逼争,會(huì)比用Debug打包出來(lái)的體積更小一點(diǎn)。

這里我們選擇一個(gè)Duplicate “Debug” Configuration劝赔,因?yàn)槲覀冃碌沫h(huán)境需要debug誓焦,添加完了之后就會(huì)多了一套Configuration了,這一套其實(shí)是包含了一些編譯參數(shù)的配置集合着帽。如果此時(shí)項(xiàng)目里面有cocopods的話杂伟,打開(kāi)Configuration Set就會(huì)發(fā)現(xiàn)是如下的樣子:

在我們自己的項(xiàng)目里面用了Pod,打開(kāi)配置是會(huì)看到如下信息


注意:剛剛新建完Build Configuration之后启摄,這時(shí)如果有pod稿壁,請(qǐng)立即執(zhí)行一下


pod install  

pod安裝完成之后會(huì)自動(dòng)生成xcconfig文件,如果你手動(dòng)新建這個(gè)xcconfig歉备,然后把原來(lái)的debug和release對(duì)應(yīng)的pod xcconfig文件內(nèi)容復(fù)制進(jìn)來(lái)傅是,這樣做是無(wú)效的,需要pod自己去生成xcconfig文件才能被識(shí)別到蕾羊。

新建完Build Configuration喧笔,這個(gè)時(shí)候需要新建pod里面對(duì)應(yīng)的Build Configuration,要不然一會(huì)編譯會(huì)報(bào)錯(cuò)龟再。如果沒(méi)用pod书闸,可以忽略一下這一段。

如下圖新建一個(gè)對(duì)應(yīng)之前Porject里面新建的Build Configuration


2. 新建Scheme

接下來(lái)我們要為新的Configuration新建一個(gè)編譯Scheme利凑。


新建完成之后浆劲,我們就可以編輯剛剛新建的Scheme,這里可以把Run模式和Archive都改成新建Scheme哀澈。如下圖:

注意:如果是使用了Git這些協(xié)同工具的同學(xué)這里還需要把剛剛新建的Scheme共享出去牌借,否則其他人看不到這個(gè)Scheme。選擇“Manage Schemes”

3. 新建User-defined Build Settings

再次回到Project的Build Settings里面來(lái)割按,Add User-Defined Setting膨报。


我們這里新加入2個(gè)參數(shù),CustomAppBundleld是為了之后打包可以分開(kāi)打成多個(gè)包适荣,這里需要3個(gè)不同的Id现柠,建議是直接在原來(lái)的Bundleld加上Scheme的名字即可。

CustomProductName是為了app安裝到手機(jī)上之后弛矛,手機(jī)上顯示的名字够吩,這里可以按照對(duì)應(yīng)的環(huán)境給予描述,比如測(cè)試服汪诉,UAT废恋,等等谈秫。如下圖扒寄。

這里值得提到的一點(diǎn)是鱼鼓,下面Pods的Build_DIR這些目錄其實(shí)是Pods自己生成好的,之前執(zhí)行過(guò)Pod install 之后该编,這里默認(rèn)都是配置好的迄本,不需要再改動(dòng)了。

4. 修改info.plist文件 和 Images.xcassets

先來(lái)修改一下info.plist文件课竣。

由于我們新添加了2個(gè)CustomAppBundleld 和 CustomProductName嘉赎,這里我們需要把info.plist里面的Bundle display name修改成我們自定義的這個(gè)字典。編譯過(guò)程中于樟,編譯器會(huì)根據(jù)我們?cè)O(shè)置好的Scheme去自己選擇Debug公条,Release,TestRelease分別對(duì)應(yīng)的ProductName迂曲。

我們還需要在Images.xcassets里面新添加2個(gè)New iOS App Icon靶橱,名字最好和scheme的名字相同,這樣好區(qū)分路捧。

新建完AppIcon之后关霸,再在Build Setting里面找到Asset Catalog Compiler里面,然后把這幾種模式下的App Icon set
Name分別設(shè)置上對(duì)應(yīng)的圖標(biāo)杰扫。如上圖队寇。

既然我們已經(jīng)新建了這幾個(gè)scheme,那接下來(lái)怎么把他們都打包成app呢章姓?佳遣?這里有一份官方的文檔Troubleshooting Application Archiving in Xcode這里面詳細(xì)記錄了我們平時(shí)點(diǎn)擊了Archive之后是怎么打包的。

這里分享一下我分好這些環(huán)境的心得凡伊。一切切記零渐,每個(gè)環(huán)境都要設(shè)置好Debug 和 Release!千萬(wàn)別認(rèn)為線上的版本只設(shè)置Release就好窗声,哪天需要調(diào)試線上版本相恃,沒(méi)有設(shè)置Debug就無(wú)從下手了。也千萬(wàn)別認(rèn)為測(cè)試環(huán)境的版本只要設(shè)置Debug就好笨觅,萬(wàn)一哪天要發(fā)布一個(gè)測(cè)試環(huán)境需要發(fā)Release包拦耐,那又無(wú)從下手了。我的建議就是每個(gè)環(huán)境都配置Debug 和 Release见剩,即使以后不用杀糯,也提前設(shè)置好,以防萬(wàn)一苍苞。合理的設(shè)置應(yīng)該如下圖這樣固翰。

| -------------------------- |------------------|
|           Scheme           |   Configurations |  
| -------------------------- |------------------| 
|      XXXXProjectTest       |      Debug       | 
|                            |------------------|
|                            |      Release     | 
| -------------------------- |------------------|
|      XXXXProjectAppStore   |      Debug       | 
|                            |------------------|
|                            |      Release     | 
| -------------------------- |------------------|
|      XXXXProjectUAT        |      Debug       | 
|                            |------------------|
|                            |      Release     | 
| -------------------------- |------------------|

注意這里一定要把Scheme的名字和編譯方式區(qū)分開(kāi)狼纬,選擇了一個(gè)Scheme,只是相當(dāng)于選擇了一個(gè)環(huán)境骂际,并不是代表這Debug還是Release疗琉。

我建議Scheme只配置環(huán)境,而進(jìn)來(lái)的Run和Archive來(lái)配置Debug和Release歉铝,我建議每個(gè)Scheme都按照上圖來(lái)盈简,Run對(duì)應(yīng)的Debug,Archive對(duì)應(yīng)的Release太示。

配置好上述之后柠贤,就可以選擇不同環(huán)境運(yùn)行app了±噻停可以在手機(jī)上生成不同的環(huán)境的app臼勉,可以同時(shí)安裝。如下圖餐弱。

5. 配置和獲取環(huán)境變量

接下來(lái)講幾種動(dòng)態(tài)配置環(huán)境變量的方法

1. 使用GCC預(yù)編譯頭參數(shù)GCC_PREPROCESSOR_DEFINITIONS

我們進(jìn)入到Build Settings里面宴霸,可以找到Apple LLVM Preprocessing,這里我們可以找到Preprocessor Macros在這里岸裙,我們是可以加一些環(huán)境變量的宏定義來(lái)標(biāo)識(shí)符猖败。Preprocessor Macros可以根據(jù)不同的環(huán)境預(yù)先制定不同定義的宏。


如上圖降允,圈出來(lái)的地方其實(shí)就是一個(gè)標(biāo)識(shí)符恩闻。

有了這些我們預(yù)先設(shè)置的標(biāo)識(shí)符之后,我們就可以在代碼里面寫(xiě)入如下的代碼了剧董。


#ifdef DEVELOP
#define searchURL @"http://www.baidu.com"
#define sociaURL  @"weibo.com"
#elif UAT
#define searchURL @"http://www.bing.com"
#define sociaURL  @"twitter.com"
#else
#define searchURL @"http://www.google.com"
#define sociaURL  @"facebook.com"
#endif

2. 使用plist文件動(dòng)態(tài)配置環(huán)境變量

我們先來(lái)新建3個(gè)名字一樣的plist作為3個(gè)環(huán)境的配置文件幢尚。


這里名字一樣的好處是寫(xiě)代碼方便,因?yàn)榫椭恍枰プx取“Configuration.plist”就可以了翅楼,如果名字不一樣尉剩,還要分別去把對(duì)應(yīng)環(huán)境的plist名字拼接出來(lái)才能讀取。

眾所周知毅臊,在一個(gè)文件夾里面新建2個(gè)相同名字的文件理茎,Mac 系統(tǒng)都會(huì)提示我們名字相同,不允許我們新建管嬉。那我們?cè)趺葱陆?個(gè)相同名字的文件呢皂林?這其實(shí)很簡(jiǎn)單,分別放在3個(gè)不同文件夾下面即可蚯撩。如下圖:

我就是這樣放置的础倍,大家可以根據(jù)自己習(xí)慣去放置文件。

接下來(lái)我們要做的是在編譯的時(shí)候胎挎,運(yùn)行app前沟启,動(dòng)態(tài)的copy Configuration.plist到app里面忆家,這里需要設(shè)置一個(gè)copy腳本。


進(jìn)入到我們的Target里面德迹,找到Build Phases芽卿,我們新建一個(gè)New Copy Files Phase,并且重命名為Copy Configuration Files浦辨。


echo "CONFIGURATION -> ${CONFIGURATION}"
RESOURCE_PATH=${SRCROOT}/${PRODUCT_NAME}/config/${CONFIGURATION}

BUILD_APP_DIR=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app

echo "Copying all files under ${RESOURCE_PATH} to ${BUILD_APP_DIR}"
cp -v "${RESOURCE_PATH}/"* "${BUILD_APP_DIR}/"

這一段腳本就能保證我們的Configuration.plist 文件可以在編譯的時(shí)候蹬竖,選擇其中一個(gè)打包進(jìn)我們的app沼沈。

再寫(xiě)代碼每次讀取這個(gè)plist里面的信息就可以做到動(dòng)態(tài)化了流酬。


- (NSString *) readValueFromConfigurationFile {
    NSBundle *bundle = [NSBundle mainBundle];
    NSString *path = [bundle pathForResource:@"Configuration" ofType:@"plist"];
    NSDictionary *config = [NSDictionary dictionaryWithContentsOfFile:path];
    return config[@"serverURL"];
}

這里我假設(shè)plist文件里面預(yù)設(shè)置了一個(gè)serverURL的字符串,用這種方式就可以讀取出來(lái)了列另。當(dāng)然在plist里面也可以設(shè)置數(shù)組芽腾,字典,相應(yīng)的把返回值和Key值改一下就可以了页衙。

3. 使用單例來(lái)處理環(huán)境切換

當(dāng)然使用一個(gè)單例也可以做到環(huán)境切換摊滔。新建一個(gè)單例,然后可以在設(shè)置菜單里面加入一個(gè)列表店乐,里面列出所有的環(huán)境艰躺,然后用戶選擇以后,單例就初始化用戶所選的環(huán)境眨八。和上面幾種方式不同的是腺兴,這種方式就是在一個(gè)app里面切換多種環(huán)境×啵看大家的需求页响,任取所需。

二.利用文件來(lái)配置多環(huán)境

說(shuō)道xcconfig段誊,這個(gè)官方文檔上面也提到的不是很詳細(xì)闰蚕,在網(wǎng)上尋找了一下,倒是找到了另外一份詳細(xì)非官方文檔连舍。The Unofficial Guide to xcconfig files

提到xcconfig没陡,就要先說(shuō)說(shuō)幾個(gè)概念。

1. 區(qū)分幾個(gè)概念

先來(lái)區(qū)分一下Xcode Workspace索赏、Xcode Scheme盼玄、Xcode Project、Xcode Target参滴、Build Settings 這5者的關(guān)系强岸。這5者的關(guān)系在蘋(píng)果官方文檔上其實(shí)都已經(jīng)說(shuō)明的很清楚了。詳情見(jiàn)文檔Xcode Concepts砾赔。

我來(lái)簡(jiǎn)單來(lái)解讀一下文檔蝌箍。

Xcode Workspace

A workspace is an Xcode document that groups projects and other documents so you can work on them together. A workspace can contain any number of Xcode projects, plus any other files you want to include. In addition to organizing all the files in each Xcode project, a workspace provides implicit and explicit relationships among the included projects and their targets.

workspace這個(gè)概念大家應(yīng)該都很清楚了青灼。它可以包含多個(gè)Project和其他文檔文件。

** Xcode Project**

An Xcode project is a repository for all the files, resources, and information required to build one or more software products. A project contains all the elements used to build your products and maintains the relationships between those elements. It contains one or more targets, which specify how to build products. A project defines default build settings for all the targets in the project (each target can also specify its own build settings, which override the project build settings).

project就是一個(gè)個(gè)的倉(cāng)庫(kù)妓盲,里面會(huì)包含屬于這個(gè)項(xiàng)目的所有文件杂拨,資源,以及生成一個(gè)或者多個(gè)軟件產(chǎn)品的信息悯衬。每一個(gè)project會(huì)包含一個(gè)或者多個(gè) targets弹沽,而每一個(gè) target 告訴我們?nèi)绾紊a(chǎn) products。project 會(huì)為所有 targets 定義了默認(rèn)的 build settings筋粗,每一個(gè) target 也能自定義自己的 build settings策橘,且 target 的 build settings 會(huì)重寫(xiě) project 的 build settings。

最后這句話比較重要娜亿,下面設(shè)置xcconfig的時(shí)候就會(huì)用到這一點(diǎn)丽已。

Xcode Project 文件會(huì)包含以下信息,對(duì)資源文件的引用(源碼.h和.m文件买决,frame沛婴,資源文件plist,bundle文件等督赤,圖片文件image.xcassets還有Interface Builder(nib)嘁灯,storyboard文件)、文件結(jié)構(gòu)導(dǎo)航中用來(lái)組織源文件的組躲舌、Project-level build configurations(Debug\Release)丑婿、Targets、可執(zhí)行環(huán)境孽糖,該環(huán)境用于調(diào)試或者測(cè)試程序枯冈。

** Xcode Target**

A target specifies a product to build and contains the instructions for building the product from a set of files in a project or workspace. A target defines a single product; it organizes the inputs into the build system—the source files and instructions for processing those source files—required to build that product. Projects can contain one or more targets, each of which produces one product.

target 會(huì)有且唯一生成一個(gè) product, 它將構(gòu)建該 product 所需的文件和處理這些文件所需的指令集整合進(jìn) build system 中。Projects 會(huì)包含一個(gè)或者多個(gè) targets,每一個(gè) target 將會(huì)產(chǎn)出一個(gè) product办悟。

這里值得說(shuō)明的是尘奏,每個(gè)target 中的 build setting 參數(shù)繼承自 project 的 build settings, 一旦你在 target 中修改任意 settings 來(lái)重寫(xiě) project settings,那么最終生效的 settings 參數(shù)以在 target 中設(shè)置的為準(zhǔn). Project 可以包含多個(gè) target, 但是在同一時(shí)刻病蛉,只會(huì)有一個(gè) target 生效炫加,可用 Xcode 的 scheme 來(lái)指定是哪一個(gè) target 生效。

** Build Settings**

A build setting is a variable that contains information about how a particular aspect of a product’s build process should be performed. For example, the information in a build setting can specify which options Xcode passes to the compiler.

build setting 中包含了 product 生成過(guò)程中所需的參數(shù)信息铺然。project的build settings會(huì)對(duì)于整個(gè)project 中的所有targets生效俗孝,而target的build settings是重寫(xiě)了Project的build settings,重寫(xiě)的配置以target為準(zhǔn)魄健。

一個(gè) build configaration 指定了一套 build settings 用于生成某一 target 的 product赋铝,例如Debug和Release就屬于build configaration。

** Xcode Scheme**

An Xcode scheme defines a collection of targets to build, a configuration to use when building, and a collection of tests to execute.

一個(gè)Scheme就包含了一套targets(這些targets之間可能有依賴關(guān)系)沽瘦,一個(gè)configuration革骨,一套待執(zhí)行的tests农尖。

這5者的關(guān)系,舉個(gè)可能不恰當(dāng)?shù)睦樱?br> Xcode Workspace就如同工廠良哲,Xcode Project如同車(chē)間盛卡,每個(gè)車(chē)間可以獨(dú)立于工廠來(lái)生產(chǎn)產(chǎn)品(project可獨(dú)立于workspace存在),但是各個(gè)車(chē)間組合起來(lái)就需要工廠來(lái)組織(如果用了cocopods筑凫,就需要用workspace)滑沧。Xcode Target是一條條的流水線,一條流水線上面只生產(chǎn)一種產(chǎn)品巍实。Build Settings是生產(chǎn)產(chǎn)品的秘方滓技,如果是生產(chǎn)汽水,Build Settings就是其中各個(gè)原料的配方蔫浆。Xcode Scheme是生產(chǎn)方案殖属,包含了流水線生產(chǎn),秘方瓦盛,還包含生產(chǎn)完成之后的質(zhì)檢(test)。

2. 來(lái)創(chuàng)建一個(gè)xcconfig文件

然后創(chuàng)建好了這個(gè)文件外潜,我們?cè)趐roject里面設(shè)置一下原环。

在這些地方把配置文件換成我們剛剛新建的文件。

接下來(lái)就要編寫(xiě)我們的xcconfig文件了处窥。這個(gè)文件里面可以寫(xiě)的東西挺多的嘱吗。細(xì)心的同學(xué)就會(huì)發(fā)現(xiàn),其實(shí)我們一直使用的cocopods就是用這個(gè)文件來(lái)配置編譯參數(shù)的滔驾。我們隨便看一個(gè)簡(jiǎn)單的cocopods的xcconfig文件谒麦,就是下圖這樣子:


GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Forms"
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/Forms"
OTHER_LDFLAGS = $(inherited) -ObjC -l"Forms"
PODS_ROOT = ${SRCROOT}/Pods

我們由于需要配置網(wǎng)絡(luò)環(huán)境,那可以這樣寫(xiě)

//網(wǎng)絡(luò)請(qǐng)求baseurl
REQUESTBASE_URL = @"http:\\/\\/10.20.100.1"

當(dāng)然也可以寫(xiě)成cocopods那樣

GCC_PREPROCESSOR_DEFINITIONS = $(inherited) WEBSERVICE_URL='$(REQUESTBASE_URL)' MESSAGE_SYSTEM_URL='$(MESSAGE_SYSTEM_URL)'

這里利用了一個(gè)GCC_PREPROCESSOR_DEFINITIONS編譯參數(shù)哆致。

Space-separated list of option specifications. Specifies preprocessor macros in the form foo (for a simple #define) or foo=1 (for a value definition). This list is passed to the compiler through the gcc -D option when compiling precompiled headers and implementation files.

GCC_PREPROCESSOR_DEFINITIONS 是 GCC 預(yù)編譯頭參數(shù)绕德,通常我們可以在 Project 文件下的 Build Settings 對(duì)預(yù)編譯宏定義進(jìn)行默認(rèn)賦值。

它就是在Build Settings里面的 Apple LLVM 7.X - Preprocessing - Preprocessor Macros 這里摊阀。


Preprocessor Macros 其實(shí)是按照 Configuration 選項(xiàng)進(jìn)行默認(rèn)配置的, 它是可以根據(jù)不同的環(huán)境預(yù)先制定不同定義的宏耻蛇,或者為不同環(huán)境下的相同變量定義不同的值。

xcconfig 我們可以寫(xiě)入不同的 Configuration 選項(xiàng)配置不同的文件胞此。每一個(gè) xcconfig 可以配置 Build Settings 里的屬性值, 其實(shí)實(shí)質(zhì)就是通過(guò) xcconfig 去修改 GCC_PREPROCESSOR_DEFINITIONS 的值臣咖,這樣我們就可以做到動(dòng)態(tài)配置環(huán)境的需求了。

最后還需要提的一點(diǎn)是漱牵,這個(gè)配置文件的level的問(wèn)題《嵘撸現(xiàn)在本地有這么多配置,到底哪一個(gè)最終生效呢酣胀?打開(kāi)Build 里面的level刁赦,我們來(lái)看一個(gè)例子愿卸。

我們目前可以看到有5個(gè)配置,他們是有優(yōu)先級(jí)的截型。優(yōu)先級(jí)是從左往右趴荸,依次降低的。Resolved = target-level > project-level > 自定義配置文件 > iOS 默認(rèn)配置宦焦。左邊第一列永遠(yuǎn)顯示的是當(dāng)前生效的最終配置結(jié)果发钝。

知道了這個(gè)優(yōu)先級(jí)之后,我們可以更加靈活的配置我們的app了波闹。

最后關(guān)于xcconfig配置酝豪,基本使用就這些了。但是這里面的學(xué)問(wèn)不僅僅這些精堕。

還能利用xcconfig動(dòng)態(tài)配置Build Settings里面的很多參數(shù)孵淘。這其實(shí)類似于cocopods的做法。但是有一個(gè)大神的做法很優(yōu)雅歹篓。值得大家感興趣的人去學(xué)習(xí)學(xué)習(xí)瘫证。iOS大神Justin Spahr-Summers的開(kāi)源庫(kù)xcconfigs提供了一個(gè)類權(quán)威的模板, 這是一個(gè)很好的學(xué)習(xí)使用xcconfig的庫(kù),強(qiáng)烈推薦庄撮。

最后這里有一個(gè)Demo背捌,配置了Cocopods,配置了xcconfig文件洞斯,還有Build Configuration的毡庆,大家可以看看,請(qǐng)多多指教烙如,Demo么抗。

三.利用Targets來(lái)配置多環(huán)境

配置一個(gè)多環(huán)境其實(shí)一個(gè)Scheme和xcconfig已經(jīng)完全夠用了,為什么還要有這個(gè)第三點(diǎn)呢亚铁?雖說(shuō)僅僅為了配置一個(gè)多環(huán)境這點(diǎn)“小事”蝇刀,但是利用多個(gè)Targets也能實(shí)現(xiàn)需求,只不過(guò)有點(diǎn)“興師動(dòng)眾”了刀闷。

關(guān)于構(gòu)建Targets這個(gè)技術(shù)熊泵,我也是在2年前的公司實(shí)踐過(guò)。當(dāng)時(shí)的需求是做一個(gè)OEM的產(chǎn)品甸昏。自己公司有主要產(chǎn)品顽分,也幫其他公司做OEM。一說(shuō)到OEM施蜜,大家應(yīng)該就知道Targets用到這里的妙用了卒蘸。利用Targets可以瞬間大批量產(chǎn)生大量的app。

2013年巧哥也發(fā)過(guò)關(guān)于Targets的文章,猿題庫(kù)iOS客戶端的技術(shù)細(xì)節(jié)(一):使用多target來(lái)構(gòu)建大量相似App缸沃,我原來(lái)公司在2014年也實(shí)現(xiàn)了這種功能恰起。

僅僅只用一套代碼,就可以生產(chǎn)出7個(gè)app趾牧。7個(gè)app的證書(shū)都是不同的检盼,配置也都不同,但是代碼只需要維護(hù)一套代碼翘单,就可以完成維護(hù)7個(gè)app的目標(biāo)吨枉。

下面我們來(lái)看看怎么新建Targets,有2種方法哄芜。

一種方法是完全新建一個(gè)Targets貌亭,另外一種方法是復(fù)制原有的Targets。

其實(shí)第一種方法建立出Targets认臊,之后看你需求是怎么樣的圃庭。如果也想是做OEM這種,可以把新建出來(lái)的project刪掉失晴,本地還是維護(hù)一套代碼剧腻,然后在新建的Targets 的Build Phases里面去把本地現(xiàn)有代碼加上,參數(shù)自己可以隨意配置师坎。這樣也是一套代碼維護(hù)多個(gè)app恕酸。

第二種方法就是復(fù)制一個(gè)原有的Targets,這種做法只用自己去改參數(shù)就可以了胯陋。

再來(lái)說(shuō)說(shuō)Targets的參數(shù)。

由于我們新建了Targets袱箱,相當(dāng)于新建了一個(gè)app了遏乔。所以里面的所有的文件全部都可以更改。包括info.plist发笔,源碼引用盟萨,Build Settings……所有參數(shù)都可以改,這樣就不僅僅局限于修改Scheme和xcconfig了讨,所以之前說(shuō)僅僅配置一個(gè)多環(huán)境用Targets有點(diǎn)興師動(dòng)眾捻激,但是它確實(shí)能完成目的。根據(jù)第二章里面我們也提到了前计,Targets相當(dāng)于流水線胞谭,僅次于Project的地位,可以想象男杈,有了Targets丈屹,我們沒(méi)有什么不能修改的。

PS.最后關(guān)于Targets還有一點(diǎn)想說(shuō)的,如果大家有多個(gè)app旺垒,并且這幾個(gè)app之間有超過(guò)80%的代碼都是完全一樣的彩库,或者說(shuō)僅僅只是個(gè)別界面顯示不同,邏輯都完全相同先蒋,建議大家用Targets來(lái)做骇钦,這樣只需要維護(hù)一套代碼就可以了。維護(hù)多套相同的代碼竞漾,實(shí)在太沒(méi)有效率了眯搭。一個(gè)bug需要在多套代碼上面來(lái)回改動(dòng),費(fèi)時(shí)費(fèi)力畴蹭。

這時(shí)候可能有人會(huì)問(wèn)了坦仍,如果維護(hù)一套代碼,以后這些app如果需求有不同怎么辦叨襟?繁扎?比如要進(jìn)入不同界面,跳轉(zhuǎn)不同界面糊闽,頁(yè)面也顯示不同怎么辦梳玫??這個(gè)問(wèn)題其實(shí)很簡(jiǎn)單右犹。在Targets里面的Compile Sources里面是可以給每個(gè)不同的Targets添加不同的編譯代碼的私爷。只需要在每個(gè)不同的Targets里面加入不同界面的代碼進(jìn)行編譯就可以了,在跳轉(zhuǎn)的那個(gè)界面加上宏函筋,來(lái)控制不同的app跳轉(zhuǎn)到相應(yīng)界面贝润。這樣本地還是維護(hù)的一套代碼,只不過(guò)每個(gè)Targets編譯的代碼就是這套代碼的子集了掂墓。這樣維護(hù)起來(lái)還是很方便谦纱。也實(shí)現(xiàn)了不同app不同界面,不同需求了君编。

最后

其實(shí)這篇文章的需求源自于上篇Jenkins自動(dòng)化持續(xù)集成跨嘉,有一個(gè)需求是能打不同環(huán)境的包。之前沒(méi)有Jenkins的時(shí)候就改改URL運(yùn)行一遍就好吃嘿,雖說(shuō)做法不夠優(yōu)雅祠乃,但是也不麻煩。現(xiàn)在想持續(xù)集成兑燥,只好把環(huán)境都分好亮瓷,參數(shù)配置正確,這樣Jenkins可以一次性多個(gè)環(huán)境的包一起打贪嫂。真正做到多環(huán)境的持續(xù)集成寺庄。

最后就可以打出不同環(huán)境的包了。請(qǐng)大家多多指教。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末斗塘,一起剝皮案震驚了整個(gè)濱河市赢织,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌馍盟,老刑警劉巖于置,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異贞岭,居然都是意外死亡八毯,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)瞄桨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)话速,“玉大人,你說(shuō)我怎么就攤上這事芯侥〔唇唬” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵柱查,是天一觀的道長(zhǎng)廓俭。 經(jīng)常有香客問(wèn)我,道長(zhǎng)唉工,這世上最難降的妖魔是什么研乒? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮淋硝,結(jié)果婚禮上雹熬,老公的妹妹穿的比我還像新娘。我一直安慰自己谣膳,他們只是感情好橄唬,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著参歹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪隆判。 梳的紋絲不亂的頭發(fā)上犬庇,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音侨嘀,去河邊找鬼臭挽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛咬腕,可吹牛的內(nèi)容都是我干的欢峰。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼纽帖!你這毒婦竟也來(lái)了宠漩?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤懊直,失蹤者是張志新(化名)和其女友劉穎扒吁,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體室囊,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雕崩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了融撞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盼铁。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖尝偎,靈堂內(nèi)的尸體忽然破棺而出饶火,到底是詐尸還是另有隱情,我是刑警寧澤冬念,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布趁窃,位于F島的核電站,受9級(jí)特大地震影響急前,放射性物質(zhì)發(fā)生泄漏醒陆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一裆针、第九天 我趴在偏房一處隱蔽的房頂上張望刨摩。 院中可真熱鬧,春花似錦世吨、人聲如沸澡刹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)罢浇。三九已至,卻和暖如春沐祷,著一層夾襖步出監(jiān)牢的瞬間嚷闭,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工赖临, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留胞锰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓兢榨,卻偏偏與公主長(zhǎng)得像嗅榕,于是被迫代替她去往敵國(guó)和親顺饮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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