Xcode —— 使用Multi-Target管控相似 App


前言

在公司發展過程中,除了開發維護自有品牌外,針對有實力有潛質的客戶,公司還會接受OEM「貼牌開發」的合作方式。在硬件產品方面,OEM方式主要體現于「外觀重新開模改絲印」,「PCB重新layout」和「功能定制開發」;在App方面,主要體現于「App Logo修改」,「歡迎頁面修改」,「關于我們頁面修改」,「App背景顏色修改」和「功能定制開發」。
目前公司的客戶中,大概有5個客戶是以OEM的方式進行合作的,所以,對于App,需要采用一個容易維護的方式來管控公司及所有OEM客戶的App。

問題描述

針對「前言」中描述的情況,需要解決的問題可以歸納如下:

  • 6個App的代碼需要共用,盡量減少代碼間的差異
  • 每個App的「應用名稱」、「應用圖標」、「歡迎頁面」及「關于我們頁面」均不同
  • 在個別功能或頁面在實現上,每個App均有一定差異性
  • 每個App對應的開發者帳號均不同

解決方案

在Xcode中,有一個「Mutil-Target」功能,在蘋果官方文檔中對于Target是這樣描述的:

「A target specifies a product to build and contains the instructions for building the product form a set of files in a project or workspace. A target defines a single product; it organizes the inputs into the build system -- the source files and instructions for processing those source files -- required to build that product. Projects can contain one or more targets, each of which productes one product.」

這段話大概可以理解為「同一個Xcode工程中,每一個target可以對應一個獨立的App,通過target相關的配置,可以定義每個Target(即App)的build屬性:例如「需要編譯哪些文件」、「App名稱」、「App的Bundle ID」等」。這么看來,使用Target功能,即可滿足此次需求。

添加Target的過程可分為以下幾步:

新建Target

根據需求,新Target的大部分內容跟原Target相似,所以我們使用「Duplicate」的方式來「復制生成」新Target。點擊Target名稱可以很方便地改名,假設名稱改為「NewTarget」。


設置「App名稱」

設置info.plist文件
  1. 添加「NewTarget」后,可以發現工程中多了一個「Target_copy-info.plist」,在此,我們將其名稱改為「NewTarget-info.plist」,一般來說,此文件內容不需要修改。

  2. 在「TARGETS」中選擇「NewTarget」,進入工程的「Build Setting」頁面,找到「Packaging」分類,把里面的「info.plist File」改為「NewTarget-info.plist」

  3. 此時回到「General」頁面,就可以對Bundle Identifier」和「Team」等選項進行修改了。

設置infoPlist.strings文件
  1. 在工程目錄中新建文件夾「NewTargetInfo」。

  2. 找到工程文件夾中的infoPlist.strings文件(注意,每種語言均有一個infoPlist.strings文件),將其復制到文件夾「NewTargetInfo」中。

  3. 在Xcode工程中新建Group「NewTarget-Info」,將「NewTarget-info.plist」拖到該Group中,同時,通過「Add Files to “Target”」選項將步驟2)中的infoPlist.strings文件添加到Group「NewTarget-Info」。


  4. 選中「infoPlist.strings」,在「Utilities View」中的「Target Membership」選項,選擇此「infoPlist.strings」屬于哪個Target,注意,這里不能多選,只能選中「NewTarget」。


  5. 打開「infoPlist.strings」文件,在各個語言文件中添加下述語句,其中「AppName」根據需求填寫。

    "CFBundleDisplayName" = "AppName";

添加「App圖標」及「啟動頁面」

添加「App圖標」

添加「App圖標」相對簡單

  1. 進入「Images.xcassets」中,通過「按住Option按鈕拖拽」的方式,得到原來的「AppIcon」的拷貝,將其改名為「NewTarget AppIcon」;

  2. 右鍵「Show in Finder」,將新的App圖標按照相同的名稱拷貝進文件夾,覆蓋原有圖標。

  3. 進入「NewTarget」的「General」頁面,找到「App Icons and Launch Images」分類,在「App Icons Source」選項中選擇「NewTarget AppIcon」;

添加「啟動頁面」

「啟動頁面」分兩種情況,一種是IOS7及以下版本的「啟動頁面」,一種是IOS8及以上版本的「啟動頁面」

對于IOS7及以下版本

參考「App圖標」的三步配置,即可為「NewTarget」創建新的「啟動頁面」

對于IOS8及以上版本

由于IOS8及以上版本的啟動頁面使用的是「Launch Screen」,而「Launch Screen」的樣式只能通過修改.xib頁面實現,不可編寫任何代碼。假設「Launch Screen」中只有一個ImageView元件,ImageView元件的image為「welcomePage.png」,那么,我們可以在工程中添加多個同名但不同內容的welcomePage.png,并通過「Target Membership」來定義不同的「welcomePage.png」分別關聯哪個Target,即可實現不同Target使用不同「啟動頁面」的目的。

添加預編譯宏

對于不同Target間代碼級別的差異,我們可以通過預編譯宏來實現代碼預編譯。進入「Target」的「Build Settings」界面,找到「Preprocessor Macros」選項,在「Debug」及「Release」選項中,按需增加宏定義。例如,為「NewTarget」添加宏定義

"TARGET_TYPE"="NEW_TARGET"

那么在代碼中,即可通過預編譯語句實現代碼的差別編譯。

#if TARGET_TYPE == NEW_TARGET
    //do something for NewTarget
#else
    //do something for OtherTarget
#end

Manage Schemes

最后一步!將系統默認生成的 build Scheme 名稱改為「New Target Release」即可,當然,還可以按需添加不同的 scheme.

坑!!!

奇怪的編譯問題

_Warning: The Copy Bundle Resources build phase contains this target's Info.plist file 'Simart-Info.plist'._

原因:在「Target-Info.plist」的「Target Membership」選項中誤選了某個Target,正常情況下,「Target-Info.plist」在「Target Membership」選項中是不選擇任何一個Target的。

Unable to run command 'CpResource Simart.app' - this target might include its own product.
Unable to run command 'Touch Simart.app' - this target might include its own product.

原因:在「Products」Group中的某個product的「Target Membership」中給誤選了某個Target,正常情況下product不應該關聯到任何一個Target。

App名稱無法修改

原因:在修改「NewTarget」的「InfoPlist.strings」文件時,發現無論如何修改,App名稱都會顯示OriginalTarget的App名稱,排查后發現,「OriginalTarget」的「InfoPlist.strings」的「Target Membership」中除了勾選了「OriginalTarget」外,還勾選了「NewTarget」,這就導致了在編譯「NewTarget」時,錯誤地讀取了「OriginalTarget」的「InfoPlist.strings」文件。

重新檢查一遍所有Target「InfoPlist.strings」的「Target Membership」選項,保證關聯的唯一性和正確性即可。

「啟動頁面」無法顯示

此問題出現在IOS8.0及以上版本中。

問題具體表現為:無論使用模擬器或者真機調試,在切換Target時,均會「隨機」出現「啟動頁面」變成白色。檢查了很多遍各個Target的配置,并未發現問題。

最后,Achive每個Target的AD HOC版本,并通過fir.im進行分發測試,發現每個Target的「啟動頁面」均正常,難道這是Xcode-7.2.1的Bug?目前不得而知,待后續跟進...

總結

總的來說,使用「Multi-Target」方案,算是「完美地」解決了此次需求。同時,此方案也可用于「發布獨立的測試版本」「發布有限制的App版本」等需求。

總而言之,只要理解了A target defines a single product,具體怎么用就看項目的實際需求了。

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

推薦閱讀更多精彩內容