前言
在公司發(fā)展過程中,除了開發(fā)維護自有品牌外,針對有實力有潛質的客戶喊衫,公司還會接受OEM「貼牌開發(fā)」的合作方式。在硬件產品方面杆怕,OEM方式主要體現(xiàn)于「外觀重新開模改絲印」族购,「PCB重新layout」和「功能定制開發(fā)」;在App方面陵珍,主要體現(xiàn)于「App Logo修改」寝杖,「歡迎頁面修改」,「關于我們頁面修改」互纯,「App背景顏色修改」和「功能定制開發(fā)」瑟幕。
目前公司的客戶中,大概有5個客戶是以OEM的方式進行合作的伟姐,所以收苏,對于App,需要采用一個容易維護的方式來管控公司及所有OEM客戶的App愤兵。
問題描述
針對「前言」中描述的情況鹿霸,需要解決的問題可以歸納如下:
- 6個App的代碼需要共用,盡量減少代碼間的差異
- 每個App的「應用名稱」秆乳、「應用圖標」懦鼠、「歡迎頁面」及「關于我們頁面」均不同
- 在個別功能或頁面在實現(xiàn)上,每個App均有一定差異性
- 每個App對應的開發(fā)者帳號均不同
解決方案
在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
根據(jù)需求烈和,新Target的大部分內容跟原Target相似,所以我們使用「Duplicate」的方式來「復制生成」新Target皿淋。點擊Target名稱可以很方便地改名招刹,假設名稱改為「NewTarget」。
設置「App名稱」
設置info.plist文件
添加「NewTarget」后窝趣,可以發(fā)現(xiàn)工程中多了一個「Target_copy-info.plist」疯暑,在此,我們將其名稱改為「NewTarget-info.plist」高帖,一般來說缰儿,此文件內容不需要修改。
在「TARGETS」中選擇「NewTarget」散址,進入工程的「Build Setting」頁面乖阵,找到「Packaging」分類,把里面的「info.plist File」改為「NewTarget-info.plist」
此時回到「General」頁面预麸,就可以對Bundle Identifier」和「Team」等選項進行修改了瞪浸。
設置infoPlist.strings文件
在工程目錄中新建文件夾「NewTargetInfo」。
找到工程文件夾中的infoPlist.strings文件(注意吏祸,每種語言均有一個infoPlist.strings文件)对蒲,將其復制到文件夾「NewTargetInfo」中。
-
在Xcode工程中新建Group「NewTarget-Info」贡翘,將「NewTarget-info.plist」拖到該Group中蹈矮,同時,通過「Add Files to “Target”」選項將步驟2)中的infoPlist.strings文件添加到Group「NewTarget-Info」鸣驱。
-
選中「infoPlist.strings」泛鸟,在「Utilities View」中的「Target Membership」選項,選擇此「infoPlist.strings」屬于哪個Target踊东,注意北滥,這里不能多選,只能選中「NewTarget」闸翅。
-
打開「infoPlist.strings」文件再芋,在各個語言文件中添加下述語句,其中「AppName」根據(jù)需求填寫坚冀。
"CFBundleDisplayName" = "AppName";
添加「App圖標」及「啟動頁面」
添加「App圖標」
添加「App圖標」相對簡單
進入「Images.xcassets」中济赎,通過「按住Option按鈕拖拽」的方式,得到原來的「AppIcon」的拷貝,將其改名為「NewTarget AppIcon」司训;
右鍵「Show in Finder」华蜒,將新的App圖標按照相同的名稱拷貝進文件夾,覆蓋原有圖標豁遭。
進入「NewTarget」的「General」頁面,找到「App Icons and Launch Images」分類贺拣,在「App Icons Source」選項中選擇「NewTarget AppIcon」蓖谢;
添加「啟動頁面」
「啟動頁面」分兩種情況,一種是IOS7及以下版本的「啟動頁面」譬涡,一種是IOS8及以上版本的「啟動頁面」
對于IOS7及以下版本
參考「App圖標」的三步配置闪幽,即可為「NewTarget」創(chuàng)建新的「啟動頁面」
對于IOS8及以上版本
由于IOS8及以上版本的啟動頁面使用的是「Launch Screen」,而「Launch Screen」的樣式只能通過修改.xib頁面實現(xiàn)涡匀,不可編寫任何代碼盯腌。假設「Launch Screen」中只有一個ImageView元件,ImageView元件的image為「welcomePage.png」陨瘩,那么腕够,我們可以在工程中添加多個同名但不同內容的welcomePage.png,并通過「Target Membership」來定義不同的「welcomePage.png」分別關聯(lián)哪個Target舌劳,即可實現(xiàn)不同Target使用不同「啟動頁面」的目的帚湘。
添加預編譯宏
對于不同Target間代碼級別的差異,我們可以通過預編譯宏來實現(xiàn)代碼預編譯甚淡。進入「Target」的「Build Settings」界面,找到「Preprocessor Macros」選項贯卦,在「Debug」及「Release」選項中资柔,按需增加宏定義。例如撵割,為「NewTarget」添加宏定義
"TARGET_TYPE"="NEW_TARGET"
那么在代碼中贿堰,即可通過預編譯語句實現(xiàn)代碼的差別編譯。
#if TARGET_TYPE == NEW_TARGET
//do something for NewTarget
#else
//do something for OtherTarget
#end
Manage Schemes
最后一步睁枕!將系統(tǒng)默認生成的 build Scheme 名稱改為「New Target Release」即可官边,當然,還可以按需添加不同的 scheme.
坑M庥觥W⒉尽!
奇怪的編譯問題
_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不應該關聯(lián)到任何一個Target妄辩。
App名稱無法修改
原因:在修改「NewTarget」的「InfoPlist.strings」文件時惑灵,發(fā)現(xiàn)無論如何修改,App名稱都會顯示OriginalTarget的App名稱眼耀,排查后發(fā)現(xiàn)英支,「OriginalTarget」的「InfoPlist.strings」的「Target Membership」中除了勾選了「OriginalTarget」外,還勾選了「NewTarget」哮伟,這就導致了在編譯「NewTarget」時干花,錯誤地讀取了「OriginalTarget」的「InfoPlist.strings」文件。
重新檢查一遍所有Target「InfoPlist.strings」的「Target Membership」選項楞黄,保證關聯(lián)的唯一性和正確性即可池凄。
「啟動頁面」無法顯示
此問題出現(xiàn)在IOS8.0及以上版本中。
問題具體表現(xiàn)為:無論使用模擬器或者真機調試鬼廓,在切換Target時肿仑,均會「隨機」出現(xiàn)「啟動頁面」變成白色。檢查了很多遍各個Target的配置碎税,并未發(fā)現(xiàn)問題尤慰。
最后,Achive每個Target的AD HOC版本蚣录,并通過fir.im進行分發(fā)測試割择,發(fā)現(xiàn)每個Target的「啟動頁面」均正常,難道這是Xcode-7.2.1的Bug萎河?目前不得而知荔泳,待后續(xù)跟進...
總結
總的來說,使用「Multi-Target」方案虐杯,算是「完美地」解決了此次需求玛歌。同時,此方案也可用于「發(fā)布獨立的測試版本」「發(fā)布有限制的App版本」等需求擎椰。
總而言之支子,只要理解了A target defines a single product
,具體怎么用就看項目的實際需求了达舒。