Xcode 的 Target 區(qū)分開發(fā)和生產(chǎn)環(huán)境

一些初學(xué)者可能會好奇团滥,為什么在開發(fā)應(yīng)用的時(shí)候我們需要用兩套隔離的數(shù)據(jù)庫和環(huán)境劈榨。這是因?yàn)樵谀愠掷m(xù)地開發(fā)應(yīng)用或增加新特性的時(shí)候,可能希望將開發(fā)版本和已經(jīng)存在的生產(chǎn)版本的應(yīng)用進(jìn)行區(qū)分冠跷。標(biāo)準(zhǔn)的開發(fā)實(shí)踐是針對不同版本的軟件使用不同的環(huán)境衫樊,而對我們來說,這個(gè)軟件就是 iPhone 應(yīng)用锭环。一般來講端仰,開發(fā)版應(yīng)用使用的數(shù)據(jù)庫(或其它系統(tǒng),比如說統(tǒng)計(jì)分析系統(tǒng))應(yīng)該與生產(chǎn)版應(yīng)用進(jìn)行區(qū)分田藐。在測試或者開發(fā)環(huán)境中荔烧,我們經(jīng)常使用到類似 “test comment”, “argharghargh” 和 “one more test comment” 這樣的測試數(shù)據(jù)。很顯然汽久,我們并不想讓真實(shí)的用戶看到這樣的信息鹤竭。如果應(yīng)用使用了統(tǒng)計(jì)分析系統(tǒng),在測試階段我們可能會發(fā)送成千上萬次的統(tǒng)計(jì)事件景醇。我們當(dāng)然也不想讓這樣的數(shù)據(jù)跟真實(shí)的統(tǒng)計(jì)數(shù)據(jù)混在一起臀稚。這就是為什么我們應(yīng)該區(qū)分開發(fā)環(huán)境和生產(chǎn)環(huán)境。

當(dāng)使用不同的環(huán)境開發(fā)時(shí)三痰,應(yīng)用需要知道它當(dāng)前使用的環(huán)境吧寺。一種通用的做法是在程序的 AppDelegate 中定義一個(gè)可以將應(yīng)用初始化為開發(fā)或者生產(chǎn)模式的全局變量。

enumenvironmentType{

casedevelopment, production

}

letenvironment:environmentType= .production

switchenvironment {

case.development:

//setweb service URLtodevelopment

//setAPIkeystodevelopment

print("It's for development")

case.production:

//setweb service URLtoproduction

//setAPIkeystoproduction

print("It's for production")

}

這種方法要求我們在切換環(huán)境的時(shí)候改變?nèi)肿兞康闹瞪⒔佟km然這種方法很方便也很快捷稚机,但是它存在很大的局限性。首先获搏,因?yàn)樵陂_發(fā)與生產(chǎn)環(huán)境中都使用了同一個(gè) bundle ID赖条,我們就不能在同一個(gè)設(shè)備上同時(shí)安裝應(yīng)用的不同版本。再者常熙,這種方法有可能導(dǎo)致我們不小心把開發(fā)版本的應(yīng)用提交到 App Store 上纬乍。如果忘記切換全局變量的值,我們就會提交錯(cuò)誤版本的應(yīng)用裸卫。我曾經(jīng)就有一次在提交應(yīng)用之前忘記改變?nèi)肿兞康闹捣卤幔Y(jié)果用戶就使用到了我的開發(fā)版本。這實(shí)在是太糟糕了墓贿。

在本篇文章中我將會展示一種更好的方法來區(qū)分開發(fā)和生產(chǎn)的構(gòu)建版本茧泪。更確切地來說退个,我們將會在 Xcode 中創(chuàng)建一個(gè)開發(fā)版的 target。這個(gè)方法同時(shí)適用于新建的或現(xiàn)存的大型項(xiàng)目调炬,所以你可以使用一個(gè)現(xiàn)有的項(xiàng)目來跟著這個(gè)教程進(jìn)行實(shí)踐。

使用這種方法舱馅,生產(chǎn)版和開發(fā)版的應(yīng)用都會使用同一套基礎(chǔ)代碼缰泡,但是可以有不同的圖標(biāo)、bundle ID 以及不同的數(shù)據(jù)庫代嗤。分發(fā)和提交應(yīng)用的過程也會十分簡單棘钞。更重要地,應(yīng)用的測試人員和管理人員可以在同一個(gè)設(shè)備上同時(shí)安裝應(yīng)用的兩個(gè)版本干毅,這樣他們就可以更加清楚地了解他們現(xiàn)在試用的是哪一個(gè)版本宜猜。

如何創(chuàng)建新的 Target

那么我們?nèi)绾卧?Xcode 當(dāng)中新建一個(gè)開發(fā)版的 target 呢?我會使用我提供的示例項(xiàng)目 “todo” 來一步一步地進(jìn)行演示硝逢。你可以使用自己的項(xiàng)目姨拥,并跟隨這些步驟進(jìn)行操作:

1. ?在 Project Navigator 面板上選擇項(xiàng)目,進(jìn)入設(shè)置渠鸽。在Targets小節(jié)下面叫乌,右擊現(xiàn)有的 target 并且選擇Duplicate來對一個(gè)現(xiàn)在的 target 進(jìn)行復(fù)制。

2. ?Xcode 會詢問你這個(gè) target 是不是針對于 iPad 開發(fā)的徽缚。對于本教程來說憨奸,我們只需要選擇 “Duplicate Only” 就可以了。

提示:如果你的項(xiàng)目支持通用設(shè)置凿试,則 Xcode 不會提示上面的消息排宰。

3. ?現(xiàn)在我們有了一個(gè)名為todo copy的新 target 和構(gòu)建 scheme 。讓我們來重命名一下以便于區(qū)分那婉。

TARGETS列表中選擇新創(chuàng)建的 target板甘。按下回車鍵來對它的名稱進(jìn)行編輯,并且給它起一個(gè)合適的名稱详炬。我傾向于使用 “todo Dev”虾啦。當(dāng)然你可以使用你喜歡的任何名字。

接下來痕寓,來到 “Manage Schemes…”傲醉,選擇在第 1 步中新建的 scheme,并按下回車鍵呻率。把新 scheme 命名為跟新 target 一樣的名字(?即我們上一小步中使用的名字)

4. ?這一步是可選的硬毕,不過我強(qiáng)烈建議進(jìn)行這一步。如果想讓開發(fā)版跟生產(chǎn)版的應(yīng)用更加容易區(qū)分礼仗,我們應(yīng)該提供不同的應(yīng)用圖標(biāo)和啟動(dòng)界面吐咳。這可以使測試更加清楚他們現(xiàn)在使用的版本逻悠,并且可以防止我們提交開發(fā)版本的應(yīng)用到商店中。 :grinning:

選中Assets.xcassets然后添加新的 App 圖標(biāo)韭脊。選擇 icon > App Icons & Launch Images > New iOS App Icon. 將新圖標(biāo)命名為 “AppIcon-Dev” 并且添加你需要的圖片童谒。

5. ?現(xiàn)在回到項(xiàng)目設(shè)置,選擇開發(fā)版的 target 然后修改 bundle ID沪羔〖⒁粒可以簡單地在原來的 ID 上添加一個(gè) “Dev” 后綴。如果有操作過第 4 步蔫饰,在這里確保你的 app 圖標(biāo)設(shè)置為在上一步中添加的圖標(biāo)琅豆。

6. ?Xcode 會自動(dòng)為新的 target 創(chuàng)建一個(gè) plist 文件(一般命名為 todo copy-Info.plist)÷ㄓ酰可以在項(xiàng)目的根目錄下找到這個(gè)文件茫因。將 “copy” 修改為 “Dev”,然后將它放到原來的 plist 文件下方杖剪。這樣可以更方便我們對文件進(jìn)行操作冻押。

7. ?現(xiàn)在選擇開發(fā)版 target 下的 “Build Settings”,滾動(dòng)到 “Packaging”盛嘿,然后修改指定 plist 文件為開發(fā)版 plist(即剛剛的 todo Dev.plist)翼雀。

8. ?最后,為生產(chǎn)版和開發(fā)版 target 同時(shí)設(shè)置一個(gè)預(yù)處理宏和編譯器標(biāo)志孩擂。這樣在之后的開發(fā)中我們就可以在代碼中使用這個(gè)標(biāo)識來檢測當(dāng)前運(yùn)行的應(yīng)用是哪個(gè)版本狼渊。

對于 Objective-C 項(xiàng)目,來到Building Settings类垦,滾動(dòng)到Apple LLVM 7.0 - Preprocessing狈邑。展開Preprocessor Macros并且為DebugRelease添加一個(gè)變量。對于開發(fā)版 target(即 todo Dev)蚤认,設(shè)置變量的值為DEVELOPMENT=1(校對注:等號兩邊不能有空格)米苹。相對地,設(shè)置開發(fā)版 target 的值為DEVELOPMENT=0砰琢。

對于 Swift 項(xiàng)目蘸嘶,編譯器不再支持預(yù)處理指令了。相對地陪汽,它使用了運(yùn)行期屬性(compile-time attributes)和構(gòu)建配置训唱。為了增加開發(fā)版構(gòu)建的標(biāo)志,選擇開發(fā) target挚冤。來到Build Settings况增,向下滾動(dòng)到Swift Compiler - Custom Flags小節(jié)。設(shè)置值為-DDEVELOPMENT來表明當(dāng)前為 target 為開發(fā)版训挡。

現(xiàn)在我們已經(jīng)創(chuàng)建并配置好了開發(fā)版的 target澳骤,接下來要做什么呢歧强?

使用 Target 和宏

因?yàn)樵O(shè)置過了DEV_VERSION的宏,我們就可以在代碼中利用這個(gè)宏對項(xiàng)目使用動(dòng)態(tài)檢測了为肮。這里有一個(gè)簡單的使用示例:

Objective-C:

#ifDEVELOPMENT

#defineSERVER_URL @"http://dev.server.com/api/"

#defineAPI_TOKEN @"DI2023409jf90ew"

#else

#defineSERVER_URL @"http://prod.server.com/api/"

#defineAPI_TOKEN @"71a629j0f090232"

#endif

在 Objective-C 當(dāng)中摊册,我們可以使用#if來對DEVELOPMENT的狀態(tài)進(jìn)行檢測,并且為 URL/API 設(shè)置對應(yīng)的值颊艳。

Swift:

#ifDDEVELOPMENT

letSERVER_URL="http://dev.server.com/api/"

letAPI_TOKEN="DI2023409jf90ew"

#else

letSERVER_URL="http://prod.server.com/api/"

letAPI_TOKEN="71a629j0f090232"

#endif

在 Swift 當(dāng)中茅特,我們依然可以使用#if來對構(gòu)建配置進(jìn)行動(dòng)態(tài)判斷。然而籽暇,我們不再使用#define來定義一個(gè)常量,而是簡單地使用let來定義一個(gè) Swift 中全局常量饭庞。

提示:一般情況下戒悠,我們會將上面的代碼放在 AppDelegate 當(dāng)中。不過最終取決于你想在哪里初始化應(yīng)用的配置舟山。

當(dāng)選擇 “todo Dev” 的 scheme 并運(yùn)行項(xiàng)目绸狐,我們就會創(chuàng)建一個(gè)開發(fā)版的構(gòu)建并自動(dòng)將服務(wù)器配置設(shè)置為開發(fā)版的環(huán)境。你現(xiàn)在可以放心地上傳這個(gè)開發(fā)版到 TestFlight 或者 HockeyApp 讓應(yīng)用的測試人員或者管理人員進(jìn)行測試了累盗。

以后如果需要?jiǎng)?chuàng)建一個(gè)生產(chǎn)版的構(gòu)建寒矿,只要簡單地選擇 “todo” 的 scheme。一行代碼都不需要改變若债。

關(guān)于管理多個(gè) Target 的一些注意事項(xiàng)

1.?當(dāng)為項(xiàng)目添加新文件時(shí)符相,不要忘記同時(shí)勾選多個(gè) target 來保持各個(gè) target 中的代碼一致。

2. ?如果你的項(xiàng)目中使用了 Cocoapods蠢琳,不要忘記在 podfile 中增加新的 target啊终。我們可以使用link_with來指定多個(gè) target“列耄可以在Cocoapods 文檔中找到更詳細(xì)的內(nèi)容±渡現(xiàn)在 Podfile 看起來應(yīng)該是這樣的:

source'https://github.com/CocoaPods/Specs.git'

platform:ios,'7.0'

workspace'todo'

link_with'todo','todo Dev'

pod'Mixpanel'

pod'AFNetworking'

如果使用了持續(xù)集成系統(tǒng),比如Travis CIJenkins泰讽,不要忘了每個(gè) target 的構(gòu)建和交付都要配置例衍。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市已卸,隨后出現(xiàn)的幾起案子佛玄,更是在濱河造成了極大的恐慌,老刑警劉巖累澡,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翎嫡,死亡現(xiàn)場離奇詭異,居然都是意外死亡永乌,警方通過查閱死者的電腦和手機(jī)惑申,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門具伍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人圈驼,你說我怎么就攤上這事人芽。” “怎么了绩脆?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵萤厅,是天一觀的道長。 經(jīng)常有香客問我靴迫,道長惕味,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任玉锌,我火速辦了婚禮名挥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘主守。我一直安慰自己禀倔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布参淫。 她就那樣靜靜地躺著救湖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涎才。 梳的紋絲不亂的頭發(fā)上鞋既,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機(jī)與錄音耍铜,去河邊找鬼涛救。 笑死,一個(gè)胖子當(dāng)著我的面吹牛业扒,可吹牛的內(nèi)容都是我干的检吆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼程储,長吁一口氣:“原來是場噩夢啊……” “哼蹭沛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起章鲤,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤摊灭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后败徊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帚呼,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了煤杀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片眷蜈。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖沈自,靈堂內(nèi)的尸體忽然破棺而出酌儒,到底是詐尸還是另有隱情,我是刑警寧澤枯途,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布忌怎,位于F島的核電站,受9級特大地震影響酪夷,放射性物質(zhì)發(fā)生泄漏榴啸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一晚岭、第九天 我趴在偏房一處隱蔽的房頂上張望鸥印。 院中可真熱鬧,春花似錦腥例、人聲如沸辅甥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至要销,卻和暖如春构回,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疏咐。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工纤掸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人浑塞。 一個(gè)月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓借跪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親酌壕。 傳聞我的和親對象是個(gè)殘疾皇子掏愁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

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