如果是做 OSX 或 iOS 下的應(yīng)用開發(fā)烤低,我相信 Xcode 是大家再熟悉不過的 IDE 了,有句話是這么說的:工欲善其事玻孟,必先利其器唆缴。那么,我覺得在整個(gè)項(xiàng)目開發(fā)的過程中黍翎,了解 Xcode 的項(xiàng)目管理思維還是非常必要的面徽,但實(shí)際的工作過程中,我發(fā)現(xiàn)很多人都忽視了這塊匣掸。
所以趟紊,本篇文章以大家最熟悉的面向?qū)ο笏季S來分析 Xcode 的項(xiàng)目管理方式,希望能讓大家知其然碰酝,更能知其所以然霎匈,并能將其應(yīng)用到自己的實(shí)際項(xiàng)目管理中。
抽象層級
作為一個(gè)程序員送爸,你覺得你最擅長的應(yīng)該是什么唧躲?邏輯?算法碱璃?還是數(shù)據(jù)結(jié)構(gòu)弄痹?反正肯定不是烹飪。我覺得即使前面所說的你都不擅長嵌器,只要你有足夠強(qiáng)的“抽象”能力肛真,依然能成為一個(gè)很好的程序員。
萬物都可以應(yīng)用面向?qū)ο蟮乃季S將其抽象爽航,Xcode 自然也不例外蚓让,我們這次只是從項(xiàng)目管理的角度來提取它的抽象,除此之外讥珍,從 UI 層級也可以提取出一套抽象历极,不過這并不是本篇文章所關(guān)注的重點(diǎn)。下面是我們所提取出來的抽象類圖:
這類圖相信大家一眼看上去會很熟悉衷佃,都是些我們在使用 Xcode 時(shí)經(jīng)常碰到的名詞趟卸,上面只是將它們的關(guān)系理了下。既然我們將其提取成了類氏义,那么每個(gè)類都應(yīng)該有它的職責(zé)锄列,下面便是它們的職責(zé)劃分:
Workspace
這是最頂層的類,可以設(shè)計(jì)成單例惯悠,因?yàn)檎麄€(gè) Xcode 的生命周期中邻邮,只會有一個(gè)。workspace克婶,顧名思義是工作空間筒严,內(nèi)部聚合了多個(gè) project丹泉,用于管理 project 與 project 之間的依賴關(guān)系。
Project
單個(gè)項(xiàng)目鸭蛙,作為一個(gè)項(xiàng)目嘀掸,它擁有一定的獨(dú)立性,比如兩個(gè) app 項(xiàng)目可以放置在一個(gè) workspace 中规惰。project 主要是項(xiàng)目級別的抽象睬塌,劃分的臨界點(diǎn)是復(fù)用級別,project 和 project 一般是無法復(fù)用到源碼文件層次的歇万。
Configuration
每個(gè) project 可以對應(yīng)多個(gè) configuration揩晴,也就是配置信息,這些配置信息用于編譯器的預(yù)處理贪磺、編譯硫兰、鏈接等過程中使用。
Scheme
每個(gè) project 也可以對應(yīng)多個(gè) scheme寒锚,與 configuration 所關(guān)注點(diǎn)不同劫映,scheme 關(guān)注的是 project 在最終編譯、運(yùn)行刹前、測試泳赋、歸檔等環(huán)節(jié)的一些選項(xiàng)配置信息,它可以決定在每個(gè)環(huán)節(jié)使用什么 configuration喇喉。
Target
每個(gè) project 還可以有個(gè)多個(gè) target祖今,并且至少有一個(gè) target。target 代表一個(gè)項(xiàng)目的最終輸出拣技,它繼承了 project 的配置信息千诬。target 與 target 間的聯(lián)系比起 project 與 project 之間要更加緊密,劃分的臨界點(diǎn)也是復(fù)用級別膏斤,target 與 target 是可以復(fù)用到單個(gè)源碼文件的徐绑。
在實(shí)際的操作過程中,我們常常需要明確的界定什么時(shí)候新建 project莫辨,什么時(shí)候新建 target傲茄,因?yàn)榇蟛糠謺r(shí)候,它們還是比較類似的衔掸。不過烫幕,多考慮下 target 的職責(zé)俺抽,考慮它是繼承了 project敞映,考慮它的復(fù)用級別,應(yīng)該還是可以劃分清楚的磷斧。
依賴管理
上面介紹了 Xcode 項(xiàng)目管理方面的抽象振愿,接下來我們看看 Xcode 對它們之間依賴關(guān)系的管理捷犹。這里我覺得有兩種依賴:強(qiáng)依賴、弱依賴冕末。強(qiáng)依賴是指 target 與 target 之間的依賴萍歉,弱依賴是指 project 與 project 之間的依賴(哈哈,我又創(chuàng)造了兩個(gè)名詞)档桃。在項(xiàng)目配置界面中枪孩,選擇一個(gè)項(xiàng)目中的 target,再選擇Build Phases
藻肄,我們可以看到下面這樣的界面:
上圖有兩個(gè)紅色的箭頭特別醒目蔑舞,第一個(gè)箭頭指向的 Target Dependencies,便是我所說的強(qiáng)依賴嘹屯,這里可以選定一個(gè) target 作為當(dāng)前 target 的依賴項(xiàng)攻询,這可以保證所依賴的 target 一定是在當(dāng)前 target 之前編譯。
那么弱依賴是什么呢州弟?你猜的沒錯(cuò)钧栖,就是第二個(gè)紅色箭頭所指的地方:Link Binary With Libraries,這里我們可以選擇到其它 project 中的靜態(tài)庫或 framework婆翔,當(dāng)然這也是前提拯杠。當(dāng)我們選擇了其它 project 中的 target,這就建立起了弱引用啃奴,Xcode 會保證另一個(gè) project 中的 target 在當(dāng)前 target 之前編譯阴挣。
依賴有什么用?依賴在你將項(xiàng)目按照層次劃分分別維護(hù)時(shí)就會非常有用纺腊,比如數(shù)據(jù)訪問層庫畔咧、邏輯層庫、公共輔助庫揖膜、最終應(yīng)用誓沸。它們之間的編譯順序可能需要非常明確的,這就需要關(guān)注依賴了壹粟。
Cocoa Pods 的運(yùn)作原理
稍微大點(diǎn)的項(xiàng)目拜隧,或者我們想要方便的使用第三方開源庫時(shí),可能都會選擇 cocoapods趁仙,有了上面基礎(chǔ)知識的鋪墊洪添,再來看看 cocoapods 的運(yùn)作原理就不那么復(fù)雜了。
首先 cocoapods 在 workspace 中新建立了一個(gè) project 叫 Pods雀费,每當(dāng)我們引入一個(gè)第三方庫干奢,這個(gè) project 中就會多出一個(gè) target,類型為靜態(tài)庫盏袄。這個(gè) project 中有一個(gè)固定的 target 叫 Pods忿峻,類型也是靜態(tài)庫薄啥,這個(gè)可以看做是 Pods 這個(gè) project 的默認(rèn) target,它強(qiáng)依賴了所有其他 target逛尚,但它并不會鏈接其它 target垄惧,為了使這個(gè) target 能夠正常編譯,它內(nèi)部只有一個(gè)空的類實(shí)現(xiàn):Pods-dummy
绰寞。
所以到逊,如果想要編譯 Pods 這個(gè) target,會預(yù)先編譯其它所有 target滤钱,也就是我們真正需要使用的第三方庫蕾管。
除了新建了一個(gè)項(xiàng)目,cocoapods菩暗,還將一系列的配置信息掰曾,也就是 configuraion 寫入了不同的.xcconfig
文件中,主體項(xiàng)目中停团,每個(gè) configuration 都會對應(yīng)一個(gè)這樣的文件旷坦。然后,我們在 Podfile 中指定的 target(主應(yīng)用)會弱依賴 Pods 這個(gè) target佑稠,也就是會鏈接一個(gè)叫libPods.a
的文件秒梅。前面說過了,這個(gè)靜態(tài)庫內(nèi)部其實(shí)只有一個(gè)Pods-dummy
的類舌胶,它只是作為一個(gè)跳板捆蜀,讓我們主體項(xiàng)目依賴的第三方庫能在主體項(xiàng)目前編譯,真正使用第三方庫的地方寫在了.xcconfig
文件中幔嫂,也就是OTHER_LDFLAGS
這個(gè)關(guān)鍵的配置信息辆它。
上面介紹了 cocoapods 的核心運(yùn)作原理,還有些細(xì)節(jié)也都是建立在這樣的模式之下的履恩,就不作過多詳細(xì)解釋了锰茉。所以,cocoapods 最終可以提供這樣的項(xiàng)目管理能力:
- 不同的 project 可以指定鏈接不同的或相同的的第三方庫
- 不同的 target 可以指定鏈接不同的或相同的第三方庫
- 不同的 target 可以指定不同的 configuration
- 不同的 configuration(Debug切心,Release飒筑,Custom)可以指定鏈接不同的或相同的第三方庫
從項(xiàng)目管理的角度來說,cocoapods 還是很不錯(cuò)的將 Xcode 項(xiàng)目管理的靈活性都保留了下來绽昏,并且大多都是通過.xcconfig
文件來實(shí)現(xiàn)协屡,侵入性也不大,還是非常值得使用的全谤。
自己動(dòng)手
本篇到這里也就差不多了肤晓,那么給大家留一個(gè)小實(shí)驗(yàn):
- 在一個(gè) workspace 中建立兩個(gè) project,一個(gè)是 app,一個(gè)是 static library材原。
- app 新建一個(gè) configuration 叫 inhouse沸久。
- 要求 app 只在 inhouse 配置下鏈接并使用 static library季眷。
提示:static library 項(xiàng)目中也需要建立一個(gè) inhouse 的 configuration 哦余蟹,否則若依賴建立不起來。
那么子刮,無論你自己愿不愿意動(dòng)手實(shí)驗(yàn)威酒,應(yīng)該都可以愉快的使用 Xcode 配置項(xiàng)目玩耍了吧。