一,前言
最近老是突然對Workspace,Project,Scheme,Target四者的關系有些疑惑,所以查閱資料總結一下。
二,Workspace,Project,Scheme,Target四者的定義
1. Xcode Workspace(可類比為“辦公大樓”)
定義:Workspace是組織projects和其他協同工作的一份文檔。
作用:
1. 它將一些項目以及其他的文檔組織在一起,以便於你基於它們進行工作。一個Workspace可以包含任意個xcode項目,你也可以往里面加一些你想要的文件。
2.它還維護project和target之間的顯性及隱性的依賴關系。
3. 默認workspace中的所有Xcode projects都在同一個目錄下構建,稱為workspace build directory,由於所有project的所有文件都在同一個目錄下,所以所有文件都對每個project可見。
比如兩個project使用同一個庫,則不用復制到另一個project目錄中。
workspace中的每個project都有其獨立id,同時project可以屬於多個workspace,可以單獨打開project或者在其他workspace中打開,且都不用重新配置project或者workspace。
可以使用workspace默認的build 目錄,也可以指定一個。如果project指定了構建目錄,這個目錄會被project構建時所在的workspace的build目錄覆蓋。
示例:

2. Xcode project(可理解為“在辦公大樓里的公司”)
定義:Xcode中的project是一個包含了所有文件、資源以及構建一個或者多個product所需信息的一個倉庫。
project包含編譯product所用的所有元素,並幫我們組織這些元素之間的關系。一個project可以包含一個或者多個target,target指定了如何編譯product。project定義了其內部所有target的默認編譯配置(每個target可以通過重新設置(重寫)編譯配置來定義自己的特殊編譯配置)。
project包含了以下信息:
1、對如下源文件的引用:
(1)代碼的.h文件和.m文件
(2)Libraries 和 frameworks
(3)Resource files(資源文件,如文本,xml,plist等)
(4)圖片
(5)Interface Builder files(xib、storyboard等)
2、用來組織資源文件的group(比如哪個文件放在哪個文件夾路徑下)
3、project級別的編譯配置,比如你對debug、release兩種環境的分別設置。
4、targets的配置,這些配置指定了:
(1)工程編譯的引用
(2)工程編譯所需要的資源文件的引用
(3)工程編譯的編譯配置,包括對其他target和配置的依賴關系,還包括沒有target重寫(覆蓋)的project級別的編譯配置
5、用於debug和測試程序的執行環境,這些執行環境指定了:
(1)xcode在run或debug時的可執行文件
(2)傳遞給可執行文件的命令行參數(若有)
(3)程序運行時設置的環境變量(若有)
一個project可以獨立存在,也可以包含在一個workspace下。 你可以用Xcode schemes來指定當前的target、編譯配置、可執行文件配置。
3. Xcode Scheme(可以理解為“公司里的項目團隊”)
定義:Xcode scheme 定義了可構建的target的集合、構建時可用的設置以及可執行的測試的集合。
你可以創建任意數目的scheme,但是同一時刻只有一個是活躍的。你可以指定某一個scheme應該是存儲在project中還是workspace中——如果是存儲在project中,它在所有包含這個project的workspace中都是可用的,若是存儲在workspace中,它只能在當前的workspace中可用。當你選擇一個活躍的scheme,你也就同時選擇了一個運行目的(也就是說,這個產品將要構建在那個硬件結構中)。
4. Xcode Target(可以理解為“公司里項目團隊的產品”)
定義:一個Targetd指定一個產品來構建並且包含了從項目或workspace的全部(或部分)文件中構建產品的指令。一個target定義了一個單一的產品。
它來組織構建產品的輸入文件(包含構建產品必需的所有文件:源文件,預編譯這些源文件的指令)。Project 可以包含一個或多個target,每個target產生一個產品,可對應一個不同的應用。構建產品的指令有兩種形式:構建設置和構建階段(Build settings 和 Build phases), 你可以在Xcode的項目editor中檢查並編輯它們。target繼承了project的構建設置。但是你可以在target層次覆蓋任何project的設置。在同一時刻,只有一個target是活躍的。Xcode scheme指定了那個target是活躍的。
一個target以及由它生成的產品可以與其他的target建立關系。如果構建一個target需要另一個target的輸出,我們就說第一個target依賴於第二個target。如果它們兩個都在同一個workspace中,xcode可以發現這種依賴關系,那么它就會按照需要的順序來構建產品。這種關系叫做隱式依賴。你也可以在你的構建設置中設置顯式依賴,並且你可以指定某兩個xcode可能判定為有隱式依賴的target之間沒有依賴關系。
例如:你可以構建一個庫以及一個鏈接這個庫的在同一個workspace下的應用程序。xcode可以發現這種關系並且自動先構建這個庫。當然,如果你確實需要鏈接到一個與當前workspace下不同版本的庫中,你可以在你的構建設置中創建一個顯示依賴,這將覆蓋原來的隱式依賴。
三,相關使用方法
1.在一個Xcode頁面建立多個工程
1.1建立一個工作空間MyWorkspace
Xcode里面,建立一個工作空間。File->New->Workspace,命名為Myworkspace,存放在文件夾MyWorkspace中(名字都是可以隨便命名的)。


這樣我們就建立了一個空的工作空間。然后我們就可以往這個工作空間中加入幾個Xcode工程。
1.2 使用方法一建立一個普通的Xcode工程MyApp1添加到MyWorkspace
File->New->Project 新建一個名為MyApp1的app工程文件。為了便於管理,我們把他放在MyWorkspace文件夾中。創建完成后
在工作空間的Xcode工程中,File->Add File To "MyWorkplace",選中剛才創建的MyApp1工程。這樣MyApp1工程就添加到了MyWorkplace中了。




1.3. 使用方法二建立一個普通的Xcode工程MyApp2添加到MyWorkspace。
我們用另外一種方法添加一個工程到MyWorkplace工作空間中。
File->New->Project 新建一個名為MyApp2的app工程文件。在存放工程的界面中,將下面的Add to : 選擇成MyWorkspace。這樣MyApp2工程就添加到了MyWorkplace中。到此,我們就可以在一個Xcode的界面中同時管理兩個工程了。


1.4. 建立一個SDK工程MySDK添加到MyWorkspace。實現聯編。
但是多工程使用的精髓並不在這里,而在於兩個工程連編。
我們新建一個名為MySDK的.a庫。然后將這個MySDK工程添加到MyWorkplace,來實現MyApp2與MySDK聯調。
File->New->Project->選擇Static Library ,按照方法二添加到MyWorkspace。然后在MySDK里面創建一個sayHello類方法。在方法中打一個斷點。將.a庫拉到MyApp2里面。在ViewController里面調用sayHello方法。執行之后,斷點就會停在MySDK工程中的里面。這樣就可以在兩個工程進行調試了。








2.在同一個xcode工程里面創建多個項目
2.1首先,先創建第一個Test1工程(項目),並選中Test1工程
點擊下面的+號
接着,跟創建新項目一樣的操作,創建項目Test2。
點擊『Finish』,就完成在同一工程創建兩個項目了,再創建多個項目,按照以上操作即可。
但有一點需要注意的是:
在同一時間,XCode只能對同一工程中的某一個項目進行操作,具體要操作哪個項目,可以按以下操作:
3.在一個工程創建兩個不同版本的應用
一般來說有兩種實現方法:
-
一個把當前工程拷貝然后再修改, 這樣做會導致后期維護成本過高, 每次修改都要同時改兩個工程, 到后期修改簡直提心掉膽, 不過操作傻瓜式.
-
另外一個種就是在一個Project里面創建兩個Target, 然后通過判斷Target來修改代碼, 這樣都是基於同一套代碼做修改, 只是部分不相同的地方通過Target來添加不同代碼, 后期修改維護成本低, 推薦大家使用這種方式.
第一步:創建兩個Target:
1.首先先選中Target一個已經存在的版本, 右鍵 Duplicate
2. 然后在彈出來的選擇框選擇 Duplicate Only
3 創建完之后你的新Target應該是和我的一樣, 接下來我們就要修改Target, Scheme, Info-plist, 如圖這樣修改:
4.修改完了之后Target, Scheme, plist的名字之后, 你需要在新的Target添加對應的plist文件, 修改CFBundleDisplayName就可以修改應用的名字了.
5.還要記得修改一下Product Name 不然你的Bundle Identifier的后綴名有copy和你的Target名字不一樣, 你還需要在Bundle Setting做一下修改.
第二步,開始為兩個不同的應用添加不同的AppIcon, LaunchImage
1. 在這個選擇使用Images.xcassets里面設置AppIcon和LaunchImage, 注意這里一個是AppIcon,另一個是AppIcon-2, 以后編譯Target的時候他就會跟隨這里的設置去拿了開機圖和Icon
2.進入Images.xcassets看下圖片是不是都是勾選了兩個Target, 保持和我下圖一樣的勾選, 如果沒有勾選的話, 你在編譯的不同Target的時候會獲取不到資源.
3.選擇不同Target進行編譯, 你的運行結果應該和我的截圖一樣, 有着不同的AppName和AppIcon,還有不同的LaunchImage,但是代碼是共用, 到這里你已經成功了一半了, 接下來你肯定是想知道如何在代碼里面區別不同Target, 然后給它們添加其他的特性.
第三步,在代碼里面利用宏定義來區分不同的Traget
1.在Bundle Setting里面設置一下Proprecessor Macros添加一份KFREE KPRO的參數來區分到底是那個Traget. 在代碼里面為需要用到這個宏去判斷代碼塊.
2.在代碼里面添加Proprecessor Macros里面宏定義, 你就會發現編譯之前Xcode就會智能的選擇不同代碼. 這樣你就共用一個項目管理兩個不同版本的應用了, 大部分的代碼都復用, 維護管理非常輕松.