如何使用 Xcode Targets 管理開發和生產版本?

OneAPM官方技術部落格發表於2016-02-26

在開始此教程之前,我們假設你已經完成了應用程式的開發和測試,現在準備提交生產釋出。問題是,某些 Web 服務 URLs 指向測試伺服器,而 API keys 則為測試環境而配置。在提交應用程式給蘋果稽核之前,你需要修改所有這些 API keys 和 URLs以適應生產環境。這很正常,對吧?但是,除了將這些值在開發和生產環境之間來回更改,是否存在更好的方法來管理開發和生產版本呢?這正是筆者將與你討論的。

下面開始我們的教程!

首先,你們中的一些人可能想知道為什麼在開發應用時,要使用兩個單獨的資料庫和環境。原因是,隨著你持續不斷的構建新的功能或開發應用,你想確保開發版本和現有的生產版本相互區分。標準軟體開發過程旨在針對軟體(在我們的案例中,即為iPhone應用)的不同版本,使用不同的環境。開發版本的應用通常使用一個不同於生產版本的資料庫(或其他系統,比如分析)。這就是為什麼我們應該在不同的環境中使用不同的伺服器和資料庫。開發人員通常在測試期間使用虛擬影像或資料。在測試或開發環境中,通常會使用一些測試資料,比如“test comment”,“argharghargh”和“one more test comment”。很明顯,你可不希望真實使用者看到這樣的訊息。如果你的應用使用了分析系統,你可能在測試階段傳送成千上萬的事件。同樣,你不想在同一個資料庫中混合測試資料和生產資料。這就是為什麼總是推薦使用相互獨立的開發和生產環境。

在使用兩個獨立的環境時,你的應用需要一種方法來找出它應該連線的環境。一個常用的方法是在主app delegate中定義一個全域性變數,將應用初始化為開發或生產模式。

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")
}

這種方法需要你在每次切換環境時,改變全域性變數。儘管還算快速和方便,這種方法也有一些重大的限制。首先,因為我們在開發和生產環境中使用同一個bundle ID,你不能在同一個裝置上安裝兩個應用版本。當你想在同一臺裝置上測試應用的開發版本,但目前仍在使用應用的生產版本時,這就非常不方便。此外,這種方法可能會意外地將應用的開發版本釋出到應用商店。如果你忘了改變單一的全域性變數,你就會發布錯誤的應用程式。筆者記得有一次在應用提交之前,忘記改變全域性變數,使用者獲得的就是應用的開發版本。那簡直是一場災難。

在本文中,筆者將向你展示一個更好的方法,來區分開發和生產版本。具體來說,我們將在XCode中建立一個開發Target。此方法同時適用於新的,和現有的大型專案,所以你可以使用一個現有的應用程式,來學習本教程。

通過使用這種方法,應用的生產和開發版本將具有相同的基礎程式碼,但可以有不同的圖示,bundle ID,並指向不同的資料庫。釋出和提交過程非常簡單。最重要的是,測試人員和經理可以在同一裝置上,安裝應用程式的兩個版本,所以他們完全清楚正在測試的是哪個版本。

如何建立一個新的Target

如何在Xcode中建立一個開發Target?筆者將使用自己的模板專案“todo”,逐步演示整個過程。你可以使用自己的專案,按部就班即可:

  1. 在Project Navigator皮膚中找到專案設定。在Targets區域,右鍵單擊現有target,並選擇Duplicate複製現有的target。

enter image description here

  1. Xcode會問你,新target是否為iPad而開發。對於本教程,我們選擇 “Duplicate Only”。 enter image description here

Note: If your project supports universal devices, Xcode will not prompt the above message. 注意:如果你的專案支援通用裝置,Xcode則不會提示上述訊息。

  1. 現在,我們有了一個新的target,和一個新的構建scheme,名為todo copy。讓我們對它重新命名,使其更容易理解。

    • 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鍵來編輯文字,選擇一個更合適的名字。筆者更喜歡“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.)
    • 接下來,選擇“Manage Schemes…”,選擇你在步驟1中建立的新scheme,按下“Enter”。使scheme名稱和新的target名稱一樣(也就是你為新target選擇的名稱。)

enter image description here

  1. 步驟4是可選的,但強烈推薦。如果你想簡單的區分開發和生產版本,你應該為每個版本使用單獨的圖示和啟動螢幕。這將使你的測試人員很清楚地知道他們正在使用哪個應用,防止你釋出開發版本的應用。:)

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,並新增一個新的圖示。右擊icon> App Icons & Launch Images > New iOS App Icon。將新圖示重新命名為“AppIcon-Dev”,然後新增自己的圖片。 enter image description here

5.現在回到專案設定,選擇你的開發target,並更改bundle identifier。比如,你可以在原ID上簡單地新增“Dev”。如果你執行了步驟4,確保你把應用圖示設定為在上一步中建立的那個。 enter image description here

6.Xcode 將為你的target自動新增plist檔案 (比如todo copy-Info.plist)。你可以在專案的根目錄中找到它。將它從“copy”重新命名為“Dev”,並將其儲存在原始的plist檔案下。這樣,你就能方便管理檔案。

7.現在開啟開發target 的“Build Settings”,滾動到“Packaging”,將值更改為開發plist檔案(比如todo Dev.plist)。 enter image description here

8.最後,我們將為生產和開發targets配置一個預處理巨集/編譯器標記。這樣,之後我們就可以在程式碼中使用標記來檢測正在執行的是應用程式的哪個版本。

對於Objective - C專案,選擇Build Settings,滾動到Apple LLVM 7.0 - Preprocessing。展開Preprocessor Macros,新增Debug和Release fields變數。對於開發target (比如todo Dev),將值設定為DEVELOPMENT=1。換句話說,將值設定為DEVELOPMENT=0來表示生產版本。 enter image description here enter image description here

對於Swift專案,編譯器不再支援前處理器指令。相反,它使用編譯時屬性和構建配置。新增一個標識,來標示開發版本,選擇開發target。選擇Build Settings和向下滾動到Swift Compiler—Custom Flags部分。將值設定為-DDEVELOPMENT來標示target為開發版本。 enter image description here

現在,你已經建立和配置完成開發target,下一步是什麼?

使用target和巨集

通過配置巨集DEV_VERSION,我們可以在程式碼中使用它,為你的專案執行動態編譯。下面是一個簡單的例子:

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的情況,並相應地設定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為動態編譯評估構建配置。然而,不是使用# define來定義原始常量,在Swift中,我們簡單地使用let來定義全域性常量。

注意:通常情況下,你應該把上面的程式碼放入app delegate。但實際上取決於你在哪裡初始化應用的設定。

現在,當你選擇“todo Dev” scheme,並執行這個專案,你將自動建立開發版本,伺服器配置設定為開發環境。你現在可以向TestFlight或HockeyApp上傳開發版本,供你的測試人員和管理人員進行測試。

之後,如果你需要建立一個生產版本,簡單地選擇“todo” scheme 即可。不需要任何程式碼更改。

管理多個Targets的一些提示

1.當你將新檔案新增到專案時,別忘了同時選擇兩個Targets,保持程式碼在兩個版本中同步。 enter image description here

2.如果你使用Cocoapods,別忘了將新的target新增到podfile。你可以使用 link_with來指定多個targets。你可以進一步查詢Cocoapods documentation瞭解更多細節。你的podfile看起來應該像這樣:

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

你覺得本教程如何?你是如何管理開發和生產版本的?請和我分享你的想法。

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

OneAPM Mobile Insight ,監控網路請求及網路錯誤,提升使用者留存。訪問 OneAPM 官方網站感受更多應用效能優化體驗,想閱讀更多技術文章,請訪問 OneAPM 官方技術部落格

本文轉自 OneAPM 官方部落格

相關文章