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

在開始此教程之前,我們假設你已經完成了應用程序的開發和測試,現在準備提交生產發布。問題是,某些 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 官方博客

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容