在開始此教程之前剪个,我們假設(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)目掖鱼,按部就班即可:
- 在Project Navigator面板中找到項(xiàng)目設(shè)置然走。在Targets區(qū)域,右鍵單擊現(xiàn)有target戏挡,并選擇
Duplicate
復(fù)制現(xiàn)有的target芍瑞。
-
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ì)提示上述消息竟贯。
- 現(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選擇的名稱盛泡。)
- 步驟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”座泳,然后添加自己的圖片惠昔。
5.現(xiàn)在回到項(xiàng)目設(shè)置,選擇你的開發(fā)target挑势,并更改bundle identifier镇防。比如,你可以在原ID上簡(jiǎn)單地添加“Dev”潮饱。如果你執(zhí)行了步驟4营罢,確保你把應(yīng)用圖標(biāo)設(shè)置為在上一步中創(chuàng)建的那個(gè)。
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)勤晚。
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)版本您朽。
對(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ā)版本耻煤。
現(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è)版本中同步。
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 官方博客