怎樣使用Xcode的Targets來管理開發(fā)版本和生產(chǎn)版本的構(gòu)建

原文:How to Use Xcode Targets to Manage Development and Production Builds
作者:EugeneTrapeznikov

想象一下,你已經(jīng)完成了應(yīng)用程序的開發(fā)和測試,現(xiàn)在準(zhǔn)備提交正式版本。問題是,一些web服務(wù)的url指向了測試服務(wù)器,同時API密鑰被配置用于測試環(huán)境。在提交app給蘋果審核前,你需要修改所有這些API密鑰和URL以適應(yīng)生產(chǎn)版本。這聽起來還好,對吧?但是相較于在開發(fā)環(huán)境和生產(chǎn)環(huán)境之間來回修改相關(guān)數(shù)值,有沒有更好的方法來處理開發(fā)和生產(chǎn)版本的構(gòu)建?這正是接下來Eugene要和你討論的。

  • 進(jìn)入Eugene的教程

對于初學(xué)者來說,有些人可能會奇怪,在App開發(fā)過程中,為什么需要使用兩個單獨(dú)的數(shù)據(jù)庫和環(huán)境。原因是當(dāng)你繼續(xù)構(gòu)建新的功能特性或繼續(xù)開發(fā)你的應(yīng)用,你希望區(qū)分開現(xiàn)有的公開版本和生產(chǎn)版本。

標(biāo)準(zhǔn)的軟件開發(fā)實(shí)踐是在不同的開發(fā)環(huán)境下開發(fā)不同版本的軟件,像我們案例中講到的開發(fā)iphone應(yīng)用。應(yīng)用程序的開發(fā)版本通常使用一個不同于生產(chǎn)環(huán)境的數(shù)據(jù)庫(或如分析的其他系統(tǒng))。這就是為什么我們應(yīng)該為不同的環(huán)境中使用單獨(dú)的服務(wù)器和數(shù)據(jù)庫。開發(fā)人員在測試期間通常都使用虛擬圖像或虛擬數(shù)據(jù)。在測試環(huán)境中,使用諸如 “test comment”, “argharghargh” 和 “one more test comment”之類的測試數(shù)據(jù)并不少見。顯然,你不希望你的真實(shí)用戶看到這樣的消息。如果你的應(yīng)用程序使用了一個分析系統(tǒng)的情況下,你甚至?xí)跍y試階段發(fā)送成千上萬的事件。同樣的,你不會把測試數(shù)據(jù)和生產(chǎn)數(shù)據(jù)放在同一個數(shù)據(jù)庫中。這就是為什么總是推薦區(qū)分開發(fā)和生產(chǎn)環(huán)境。

在使用兩個獨(dú)立的環(huán)境時,你的應(yīng)用程序需要有一個辦法找出它應(yīng)該連接到的環(huán)境。一種常用的方法是在你的主應(yīng)用代理里定義一個全局變量,它會將您的應(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)境時改變?nèi)肿兞俊km然這種方法也許快捷,方便,但是它有一些重要的限制。首先,因?yàn)槲覀冊陂_發(fā)和生產(chǎn)兩個環(huán)境中使用一個Bundle ID,你不能在一臺設(shè)備上安裝應(yīng)用的兩個版本。當(dāng)你需要要測試開發(fā)版本的應(yīng)用程序時,同時仍在該設(shè)備上使用生產(chǎn)版本的應(yīng)用,這就變的不方便了。此外,這種方法很有可能將應(yīng)用的開發(fā)版本上傳到應(yīng)用商店。如果你忘記了改變這個全局變量,你將會上傳錯誤的應(yīng)用給你的用戶。我記得有一次在提交應(yīng)用程序到應(yīng)用商店之前我忘記改變?nèi)肿兞浚脩粝螺d的是應(yīng)用的開發(fā)版本,這是可怕的。

在這篇文章中,我將展示一個更好的方法來區(qū)分開發(fā)和生產(chǎn)構(gòu)建。具體而言,我們將在Xcode中創(chuàng)建一個開發(fā)的target。這種方法法適用于新的和現(xiàn)有的大型項(xiàng)目,所以你可以用一個現(xiàn)有的應(yīng)用程序?qū)φ毡窘坛獭?/p>

通過應(yīng)用這種方法,應(yīng)用的開發(fā)和生產(chǎn)版本將使用相同的基礎(chǔ)代碼,但可以有不同的圖標(biāo),bundle ID 和指向不同的數(shù)據(jù)庫。發(fā)布和提交過程將會非常簡單。最重要的是,你的測試人員和經(jīng)理可以在同一設(shè)備上安裝兩個版本的應(yīng)用程序,所以他們完全知道他們在體驗(yàn)?zāi)膫€版本。

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

所以你如何在Xcode中創(chuàng)建一個開發(fā)的target?我使用示例項(xiàng)目“todo”引導(dǎo)您一步一步完成整個過程。您也可以使用自己的項(xiàng)目并按照步驟:

  1. 在項(xiàng)目的導(dǎo)航面板進(jìn)入項(xiàng)目設(shè)置。在Targets區(qū)域下,右鍵單擊現(xiàn)有目標(biāo)并選擇 Duplicate 復(fù)制現(xiàn)有的目標(biāo)。
    640-0.jpeg
  2. Xcode會詢問你新的target是否是為iPad開發(fā)。對于本教程,我們只是選擇“Duplicate Only”。
    640-1.jpeg

    提示:如果您的項(xiàng)目支持通用設(shè)備,Xcode不會提示上述消息。
  3. 現(xiàn)在我們有一個名為todo copy的新的target和build scheme。重命名并使之更容易理解。
  • 在Targets列表中選擇新的target。按Enter鍵編輯文本,添加一個更合適的名字。我更傾向于“todo Dev”。你可以自由選擇任何你喜歡的名字。
  • 接下來,找到“Manage Schemes…”,選擇您在步驟1中創(chuàng)建的shceme,并按“輸入”,使scheme的名稱和新的target的名稱相同(這是你為新的target所選擇的名字)


    640-2.jpeg
  1. 步驟4是可選的,但強(qiáng)烈推薦。如果你想簡單地區(qū)分開發(fā)和生產(chǎn)版本構(gòu)建,你應(yīng)該為每個版本使用單獨(dú)的icon和啟動頁。這將使測試人員更清晰地知道正在使用哪個app,防止上傳開發(fā)版本。
    跳到 Assets.xcassets 添加一個新的圖標(biāo)。右擊圖標(biāo) > App Icons & Launch Images> New iOS App Icon. 新圖標(biāo)重命名為AppIcon-Dev同時添加自己的圖片。

    640-3.jpeg

  2. 現(xiàn)在回到項(xiàng)目設(shè)置,選擇您的開發(fā)target,并改變Bundle Identifier。你可以簡單地將“Dev”追加到原來的ID上。如果執(zhí)行了步驟4,請確保更改應(yīng)用app icon,設(shè)置為在上一步中創(chuàng)建的。


    640-4.jpeg
  3. Xcode會自動為你的target添加plist文件(如todo copy-Info.plist)。你可以在項(xiàng)目的根文件夾找到它。將它從“copy”重命名為“Dev”,并將它放在原始的plist文件下。這里你將更容易管理文件。

  4. 現(xiàn)在打開你開發(fā)targetBuild Settings,滾動到Packaging,并將值改為開發(fā)的plist文件(todo Dev.plist)。

    640-5.jpeg

  5. 最后,我們會為生產(chǎn)和開發(fā)target配置預(yù)處理宏/編譯器標(biāo)識。之后我們就可以使用該標(biāo)識在我們的代碼來檢測應(yīng)用程序正在運(yùn)行的版本。
    對于Objective-C的項(xiàng)目,去到Build SettingsApple LLVM 7.0 - Preprocessing。拓展Preprocessor Macros在Rebug和Release區(qū)域添加一個變量。對于開發(fā)target(即todo Dev),將該值設(shè)置為DEVELOPMENT = 1。另一個,將值設(shè)為DEVELOPMENT=0來表示生產(chǎn)版本。

    640-6.jpeg

    640-7.jpeg

    對于swift的項(xiàng)目,編譯器不再支持預(yù)處理指令。作為替代,它使用編譯時的屬性和build配置。選中開發(fā)target,添加一個標(biāo)識表示開發(fā)版本。找到Build Setting往下滾動到Swift Compiler - Custom Flags部分。將值設(shè)為-DDEVELOPMENT表示這個target作為開發(fā)版本。
    640-8.jpeg

現(xiàn)在,您已經(jīng)創(chuàng)建并配置了開發(fā)target,下一步呢?

  • 使用Target和宏

根據(jù)已配置的宏DEV_VERSION,我們可以在代碼中利用它動態(tài)地編譯項(xiàng)目。下面是一個簡單的例子:

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

Objective-C中你可以使用#if檢查DEVELOPMENT的環(huán)境,并相應(yīng)的設(shè)置URLs/ API密鑰。

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`判定build的參數(shù)動態(tài)編譯。然而,除了使用`#define`定義基本常量,在swift中我們也可以用`let`定義一個全局常量。
*提示:通常,你會把上面的代碼放在app delegate中。但這最終是取決于你在哪里初始化應(yīng)用程序設(shè)置。*

現(xiàn)在,當(dāng)您選擇“todo Dev”scheme運(yùn)行項(xiàng)目,你創(chuàng)建開發(fā)版本會自動將服務(wù)器的配置設(shè)置為開發(fā)環(huán)境。現(xiàn)在,您可以上傳開發(fā)版本到TestFlight 或 HockeyApp供測試人員和管理人員來測試。
接著如果你需要創(chuàng)建一個生產(chǎn)版本,您可以簡單地選擇"todo"scheme。不需要更改代碼。

**管理多個target的一些注意事項(xiàng)**

1. 當(dāng)你添加新的文件到項(xiàng)目中,不要忘記選擇兩個target,以保持你的代碼同步在兩個版本。
![640-9.jpeg](http://upload-images.jianshu.io/upload_images/1748817-48ad8b9cfd0d7908.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
2. 如果你使用的CocoaPods,不要忘了添加新的target到你的podfile中。您可以使用`link_with`指定多個target。您可以進(jìn)一步細(xì)節(jié)請查閱的 CocoaPods 文檔。你的podfile看起來是這樣的:
![640-10.jpeg](http://upload-images.jianshu.io/upload_images/1748817-d6fdd9ee9a720c44.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
3. 如果你使用持續(xù)集成系統(tǒng),如 Travis CI 或Jenkins,別忘了配置兩個target的build和deliver。
[.](https://mp.weixin.qq.com/s?__biz=MjM5OTM0MzIwMQ==&mid=2652546114&idx=1&sn=67e479d82e0d0a662b05082fe74f731b&scene=0&key=77421cf58af4a653c8399f6b45841a85c270e9c5a3a27be12bf54eb8e0f4ef3abd3fd0774f444128ce7a65dc65673883&ascene=7&uin=NTk5NjY4MDAw&devicetype=iPhone+OS9.3.2&version=16031510&nettype=WIFI&fontScale=100&pass_ticket=RvqmZR25hWgBcY4bjjgmBhNXNIEICVVC%2FJ1rHW3D8AiLKzaNJKaKDqdSrCnfUcML)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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