如何使用 Xcode Targets 管理開發(fā)和生產(chǎn)版本?

在開始此教程之前剪个,我們假設(shè)你已經(jīng)完成了應(yīng)用程序的開發(fā)和測(cè)試秧骑,現(xiàn)在準(zhǔn)備提交生產(chǎn)發(fā)布。問(wèn)題是扣囊,某些 Web 服務(wù) URLs 指向測(cè)試服務(wù)器乎折,而 API keys 則為測(cè)試環(huán)境而配置。在提交應(yīng)用程序給蘋果審核之前侵歇,你需要修改所有這些 API keys 和 URLs以適應(yīng)生產(chǎn)環(huán)境骂澄。這很正常,對(duì)吧惕虑?但是坟冲,除了將這些值在開發(fā)和生產(chǎn)環(huán)境之間來(lái)回更改,是否存在更好的方法來(lái)管理開發(fā)和生產(chǎn)版本呢枷遂?這正是筆者將與你討論的樱衷。

下面開始我們的教程!

首先,你們中的一些人可能想知道為什么在開發(fā)應(yīng)用時(shí)酒唉,要使用兩個(gè)單獨(dú)的數(shù)據(jù)庫(kù)和環(huán)境矩桂。原因是,隨著你持續(xù)不斷的構(gòu)建新的功能或開發(fā)應(yīng)用痪伦,你想確保開發(fā)版本和現(xiàn)有的生產(chǎn)版本相互區(qū)分侄榴。標(biāo)準(zhǔn)軟件開發(fā)過(guò)程旨在針對(duì)軟件(在我們的案例中,即為iPhone應(yīng)用)的不同版本网沾,使用不同的環(huán)境癞蚕。開發(fā)版本的應(yīng)用通常使用一個(gè)不同于生產(chǎn)版本的數(shù)據(jù)庫(kù)(或其他系統(tǒng),比如分析)辉哥。這就是為什么我們應(yīng)該在不同的環(huán)境中使用不同的服務(wù)器和數(shù)據(jù)庫(kù)桦山。開發(fā)人員通常在測(cè)試期間使用虛擬圖像或數(shù)據(jù)。在測(cè)試或開發(fā)環(huán)境中醋旦,通常會(huì)使用一些測(cè)試數(shù)據(jù)恒水,比如“test comment”,“argharghargh”和“one more test comment”饲齐。很明顯钉凌,你可不希望真實(shí)用戶看到這樣的消息。如果你的應(yīng)用使用了分析系統(tǒng)捂人,你可能在測(cè)試階段發(fā)送成千上萬(wàn)的事件御雕。同樣矢沿,你不想在同一個(gè)數(shù)據(jù)庫(kù)中混合測(cè)試數(shù)據(jù)和生產(chǎn)數(shù)據(jù)。這就是為什么總是推薦使用相互獨(dú)立的開發(fā)和生產(chǎn)環(huán)境酸纲。

在使用兩個(gè)獨(dú)立的環(huán)境時(shí)捣鲸,你的應(yīng)用需要一種方法來(lái)找出它應(yīng)該連接的環(huán)境。一個(gè)常用的方法是在主app delegate中定義一個(gè)全局變量闽坡,將應(yīng)用初始化為開發(fā)或生產(chǎn)模式摄狱。

enum environmentType {
   case development, production
}

let environment:environmentType = .production

switch environment {
case .development:
    // set web service URL to development
    // set API keys to development
    print("It's for development")
case .production:
    // set web service URL to production
    // set API keys to production
    print("It's for production")
}

這種方法需要你在每次切換環(huán)境時(shí),改變?nèi)肿兞课尬纭1M管還算快速和方便,這種方法也有一些重大的限制祝谚。首先宪迟,因?yàn)槲覀冊(cè)陂_發(fā)和生產(chǎn)環(huán)境中使用同一個(gè)bundle ID,你不能在同一個(gè)設(shè)備上安裝兩個(gè)應(yīng)用版本交惯。當(dāng)你想在同一臺(tái)設(shè)備上測(cè)試應(yīng)用的開發(fā)版本次泽,但目前仍在使用應(yīng)用的生產(chǎn)版本時(shí),這就非常不方便席爽。此外意荤,這種方法可能會(huì)意外地將應(yīng)用的開發(fā)版本發(fā)布到應(yīng)用商店。如果你忘了改變單一的全局變量只锻,你就會(huì)發(fā)布錯(cuò)誤的應(yīng)用程序玖像。筆者記得有一次在應(yīng)用提交之前,忘記改變?nèi)肿兞科胍脩臬@得的就是應(yīng)用的開發(fā)版本捐寥。那簡(jiǎn)直是一場(chǎng)災(zāi)難。

在本文中祖驱,筆者將向你展示一個(gè)更好的方法握恳,來(lái)區(qū)分開發(fā)和生產(chǎn)版本。具體來(lái)說(shuō)捺僻,我們將在XCode中創(chuàng)建一個(gè)開發(fā)Target乡洼。此方法同時(shí)適用于新的,和現(xiàn)有的大型項(xiàng)目匕坯,所以你可以使用一個(gè)現(xiàn)有的應(yīng)用程序束昵,來(lái)學(xué)習(xí)本教程。

通過(guò)使用這種方法醒颖,應(yīng)用的生產(chǎn)和開發(fā)版本將具有相同的基礎(chǔ)代碼妻怎,但可以有不同的圖標(biāo),bundle ID泞歉,并指向不同的數(shù)據(jù)庫(kù)逼侦。發(fā)布和提交過(guò)程非常簡(jiǎn)單匿辩。最重要的是,測(cè)試人員和經(jīng)理可以在同一設(shè)備上榛丢,安裝應(yīng)用程序的兩個(gè)版本铲球,所以他們完全清楚正在測(cè)試的是哪個(gè)版本。

如何創(chuàng)建一個(gè)新的Target

如何在Xcode中創(chuàng)建一個(gè)開發(fā)Target晰赞?筆者將使用自己的模板項(xiàng)目“todo”稼病,逐步演示整個(gè)過(guò)程。你可以使用自己的項(xiàng)目掖鱼,按部就班即可:

  1. 在Project Navigator面板中找到項(xiàng)目設(shè)置然走。在Targets區(qū)域,右鍵單擊現(xiàn)有target戏挡,并選擇Duplicate復(fù)制現(xiàn)有的target芍瑞。
enter image description here
  1. Xcode會(huì)問(wèn)你,新target是否為iPad而開發(fā)褐墅。對(duì)于本教程拆檬,我們選擇 “Duplicate Only”。


    enter image description here

Note: If your project supports universal devices, Xcode will not prompt the above message.
注意:如果你的項(xiàng)目支持通用設(shè)備妥凳,Xcode則不會(huì)提示上述消息竟贯。

  1. 現(xiàn)在,我們有了一個(gè)新的target逝钥,和一個(gè)新的構(gòu)建scheme屑那,名為todo copy。讓我們對(duì)它重命名艘款,使其更容易理解齐莲。
  • Select the new target in the TARGETS list. Press Enter to edit the text and put a more appropriate name. I prefer “todo Dev”. You’re free to choose whatever name you like.
  • 在TARGETS列表中,選擇新的target磷箕。按Enter鍵來(lái)編輯文本选酗,選擇一個(gè)更合適的名字。筆者更喜歡“todo Dev”岳枷。你可以自由選擇任何你喜歡的名字芒填。
  • Next, go to “Manage Schemes…”, select the new scheme you created in step 1 and press “Enter”. Make the scheme name the same as the new target name (which is the one you choose for the new target.)
  • 接下來(lái),選擇“Manage Schemes…”空繁,選擇你在步驟1中創(chuàng)建的新scheme殿衰,按下“Enter”。使scheme名稱和新的target名稱一樣(也就是你為新target選擇的名稱盛泡。)
enter image description here
  1. 步驟4是可選的闷祥,但強(qiáng)烈推薦。如果你想簡(jiǎn)單的區(qū)分開發(fā)和生產(chǎn)版本傲诵,你應(yīng)該為每個(gè)版本使用單獨(dú)的圖標(biāo)和啟動(dòng)屏幕凯砍。這將使你的測(cè)試人員很清楚地知道他們正在使用哪個(gè)應(yīng)用箱硕,防止你發(fā)布開發(fā)版本的應(yīng)用。:)

Go to Assets.xcassets and add a new icon. Right click icon > App Icons & Launch Images > New iOS App Icon. Rename the new icon to “AppIcon-Dev” and add your own images.
選擇Assets.xcassets悟衩,并添加一個(gè)新的圖標(biāo)剧罩。右擊icon> App Icons & Launch Images > New iOS App Icon。將新圖標(biāo)重命名為“AppIcon-Dev”座泳,然后添加自己的圖片惠昔。

enter image description here

5.現(xiàn)在回到項(xiàng)目設(shè)置,選擇你的開發(fā)target挑势,并更改bundle identifier镇防。比如,你可以在原ID上簡(jiǎn)單地添加“Dev”潮饱。如果你執(zhí)行了步驟4营罢,確保你把應(yīng)用圖標(biāo)設(shè)置為在上一步中創(chuàng)建的那個(gè)。


enter image description here

6.Xcode 將為你的target自動(dòng)添加plist文件 (比如todo copy-Info.plist)饼齿。你可以在項(xiàng)目的根目錄中找到它。將它從“copy”重命名為“Dev”蝙搔,并將其保存在原始的plist文件下缕溉。這樣,你就能方便管理文件吃型。

7.現(xiàn)在打開開發(fā)target 的“Build Settings”证鸥,滾動(dòng)到“Packaging”,將值更改為開發(fā)plist文件(比如todo Dev.plist)勤晚。


enter image description here

8.最后枉层,我們將為生產(chǎn)和開發(fā)targets配置一個(gè)預(yù)處理宏/編譯器標(biāo)記。這樣赐写,之后我們就可以在代碼中使用標(biāo)記來(lái)檢測(cè)正在運(yùn)行的是應(yīng)用程序的哪個(gè)版本鸟蜡。

對(duì)于Objective - C項(xiàng)目,選擇Build Settings挺邀,滾動(dòng)到Apple LLVM 7.0 - Preprocessing揉忘。展開Preprocessor Macros,添加Debug和Release fields變量端铛。對(duì)于開發(fā)target (比如todo Dev)泣矛,將值設(shè)置為DEVELOPMENT=1。換句話說(shuō)禾蚕,將值設(shè)置為DEVELOPMENT=0來(lái)表示生產(chǎn)版本您朽。

enter image description here

enter image description here

對(duì)于Swift項(xiàng)目,編譯器不再支持預(yù)處理器指令换淆。相反哗总,它使用編譯時(shí)屬性和構(gòu)建配置几颜。添加一個(gè)標(biāo)識(shí),來(lái)標(biāo)示開發(fā)版本魂奥,選擇開發(fā)target菠剩。選擇Build Settings和向下滾動(dòng)到Swift Compiler—Custom Flags部分。將值設(shè)置為-DDEVELOPMENT來(lái)標(biāo)示target為開發(fā)版本耻煤。

enter image description here

現(xiàn)在具壮,你已經(jīng)創(chuàng)建和配置完成開發(fā)target,下一步是什么哈蝇?

使用target和宏

通過(guò)配置宏DEV_VERSION棺妓,我們可以在代碼中使用它,為你的項(xiàng)目執(zhí)行動(dòng)態(tài)編譯炮赦。下面是一個(gè)簡(jiǎn)單的例子:

Objective-C:

#if DEVELOPMENT 
#define SERVER_URL @"http://dev.server.com/api/" 
#define API_TOKEN @"DI2023409jf90ew" 
#else 
#define SERVER_URL @"http://prod.server.com/api/" 
#define API_TOKEN @"71a629j0f090232" 
#endif

In Objective-C, you can use #if to check the condition of DEVELOPMENT, and set up the URLs/API keys accordingly.
在Objective - C中怜跑,你可以使用#if檢查DEVELOPMENT的情況,并相應(yīng)地設(shè)置URLs/API keys吠勘。

Swift:

#if DEVELOPMENT
let SERVER_URL = "http://dev.server.com/api/"
let API_TOKEN = "DI2023409jf90ew"
#else
let SERVER_URL = "http://prod.server.com/api/"
let API_TOKEN = "71a629j0f090232"
#endif

在Swift中性芬,你仍然可以使用#if為動(dòng)態(tài)編譯評(píng)估構(gòu)建配置。然而剧防,不是使用# define來(lái)定義原始常量植锉,在Swift中,我們簡(jiǎn)單地使用let來(lái)定義全局常量峭拘。

注意:通常情況下俊庇,你應(yīng)該把上面的代碼放入app delegate。但實(shí)際上取決于你在哪里初始化應(yīng)用的設(shè)置鸡挠。

現(xiàn)在辉饱,當(dāng)你選擇“todo Dev” scheme,并運(yùn)行這個(gè)項(xiàng)目拣展,你將自動(dòng)創(chuàng)建開發(fā)版本彭沼,服務(wù)器配置設(shè)置為開發(fā)環(huán)境。你現(xiàn)在可以向TestFlight或HockeyApp上傳開發(fā)版本备埃,供你的測(cè)試人員和管理人員進(jìn)行測(cè)試溜腐。

之后,如果你需要?jiǎng)?chuàng)建一個(gè)生產(chǎn)版本瓜喇,簡(jiǎn)單地選擇“todo” scheme 即可挺益。不需要任何代碼更改。

管理多個(gè)Targets的一些提示

1.當(dāng)你將新文件添加到項(xiàng)目時(shí)乘寒,別忘了同時(shí)選擇兩個(gè)Targets望众,保持代碼在兩個(gè)版本中同步。


enter image description here

2.如果你使用Cocoapods,別忘了將新的target添加到podfile烂翰。你可以使用 link_with來(lái)指定多個(gè)targets夯缺。你可以進(jìn)一步查詢Cocoapods documentation了解更多細(xì)節(jié)。你的podfile看起來(lái)應(yīng)該像這樣:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '7.0'
workspace 'todo'
link_with 'todo', 'todo Dev'
pod 'Mixpanel'
pod 'AFNetworking'

你覺(jué)得本教程如何甘耿?你是如何管理開發(fā)和生產(chǎn)版本的踊兜?請(qǐng)和我分享你的想法。

原文地址:http://www.appcoda.com/using-xcode-targets/

OneAPM Mobile Insight 佳恬,監(jiān)控網(wǎng)絡(luò)請(qǐng)求及網(wǎng)絡(luò)錯(cuò)誤捏境,提升用戶留存。訪問(wèn) OneAPM 官方網(wǎng)站感受更多應(yīng)用性能優(yōu)化體驗(yàn)毁葱,想閱讀更多技術(shù)文章垫言,請(qǐng)?jiān)L問(wèn) OneAPM 官方技術(shù)博客

本文轉(zhuǎn)自 OneAPM 官方博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末倾剿,一起剝皮案震驚了整個(gè)濱河市筷频,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌前痘,老刑警劉巖凛捏,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異芹缔,居然都是意外死亡执赡,警方通過(guò)查閱死者的電腦和手機(jī)籍滴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門息拜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)捕犬,“玉大人桂塞,你說(shuō)我怎么就攤上這事瘸味∶剂猓” “怎么了磅轻?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵帆锋,是天一觀的道長(zhǎng)吵取。 經(jīng)常有香客問(wèn)我,道長(zhǎng)锯厢,這世上最難降的妖魔是什么皮官? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮实辑,結(jié)果婚禮上捺氢,老公的妹妹穿的比我還像新娘。我一直安慰自己剪撬,他們只是感情好摄乒,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般馍佑。 火紅的嫁衣襯著肌膚如雪斋否。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天拭荤,我揣著相機(jī)與錄音茵臭,去河邊找鬼。 笑死舅世,一個(gè)胖子當(dāng)著我的面吹牛旦委,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播歇终,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼社证,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了评凝?” 一聲冷哼從身側(cè)響起追葡,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奕短,沒(méi)想到半個(gè)月后宜肉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡翎碑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年谬返,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片日杈。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡遣铝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出莉擒,到底是詐尸還是另有隱情酿炸,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布涨冀,位于F島的核電站填硕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏鹿鳖。R本人自食惡果不足惜扁眯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望翅帜。 院中可真熱鬧姻檀,春花似錦、人聲如沸涝滴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至僵娃,卻和暖如春概作,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背默怨。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工讯榕, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人匙睹。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓愚屁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親痕檬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子霎槐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

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