多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php開(kāi)源 > 綜合技術(shù) > 細(xì)聊 Cocoapods 與 Xcode 工程配置

細(xì)聊 Cocoapods 與 Xcode 工程配置

來(lái)源:程序員人生   發(fā)布時(shí)間:2018-06-11 16:41:02 閱讀次數(shù):7508次

前言

文章比較長(zhǎng),所以在文章的開(kāi)頭我打算簡(jiǎn)單介紹1下這篇文章將要講述的內(nèi)容,讀者可以選擇通篇細(xì)度,也能夠直接找到自己感興趣的部份。

既然是談 Cocoapods,那首先要弄明白它出現(xiàn)的背景。有經(jīng)驗(yàn)的開(kāi)發(fā)者都知道 Cocoapods 在實(shí)際使用中,常常遇到各種問(wèn)題,存在1定的使用本錢(qián),因此衡量 Cocoapods 的本錢(qián)和收益就顯得很關(guān)鍵。

Cocoapods 的本質(zhì)是1套自動(dòng)化工具。那末了解自動(dòng)化流程背后的原理就很重要,如果我們能手動(dòng)的摹擬 Cocoapods 的流程,不管是對(duì) Cocoapods 還是 Xcode 工程配置的學(xué)習(xí)都大有裨益。比如之前曾和同事研究過(guò)靜態(tài)庫(kù)嵌套的問(wèn)題,很遺憾當(dāng)時(shí)沒(méi)能解決,現(xiàn)在想來(lái)還是對(duì)相干知識(shí)理解還不夠到位。這1部份主要是介紹 Xcode 的工程配置,和 target/project/workspace 等名詞的概念。

最后,我會(huì)結(jié)合實(shí)際的例子,談?wù)勅绾伟l(fā)布自己的 Pod,提供給他人使用。算是對(duì) Cocoapods 的實(shí)踐總結(jié)。

由于實(shí)踐性的操作比較多,我為本文制作了1個(gè) demo,提交在 我的 Github: CocoaPodsDemo 上,感興趣的讀者可以下載下來(lái),研究1下提交歷史,或自己操作1遍。友誼提示: 本文所觸及的靜態(tài)庫(kù)均為摹擬器制作,請(qǐng)勿真機(jī)運(yùn)行。

為何要使用 Cocoapods

我們知道,再大的項(xiàng)目最初都是從 Xcode 提供的1個(gè)非常簡(jiǎn)單的工程模板漸漸演變來(lái)的。在項(xiàng)目的演變進(jìn)程中,為了實(shí)現(xiàn)新的功能,不斷有新的類(lèi)被創(chuàng)建,新的代碼被添加。不過(guò)除自己添加代碼,我們也常常會(huì)直接把第3方的開(kāi)源代碼導(dǎo)入到項(xiàng)目中,從而避免重復(fù)造輪子,節(jié)儉開(kāi)發(fā)時(shí)間。

直接把代碼導(dǎo)入到項(xiàng)目中看起來(lái)很容易,但在實(shí)踐進(jìn)程中,會(huì)遇到諸多問(wèn)題。這些問(wèn)題會(huì)困擾代碼的使用者,大大的增加了集成代碼的難度。

使用者的困擾

最直接的問(wèn)題就是代碼的后續(xù)保護(hù)。假定代碼的發(fā)布者在未來(lái)的某1天更新了代碼,修復(fù)了1個(gè)重大 bug 或提供了新的功能,那末使用者就很難集成這些變動(dòng)。

代碼有增有刪,如果把代碼編譯成靜態(tài)庫(kù)再提供給使用者, 就能夠省掉很多問(wèn)題。但是如果這么做的話,就會(huì)遇到另外一個(gè)經(jīng)典的問(wèn)題: “Other linker flag”。

舉個(gè)例子來(lái)講,可以在 Demo 的 BSStaticLibraryOne 這個(gè)項(xiàng)目中看到,這個(gè)靜態(tài)庫(kù)1共有兩個(gè)類(lèi),其中1個(gè)是拓展 Extension。項(xiàng)目編譯后就會(huì)得到1個(gè) .a 文件。

我們都知道靜態(tài)庫(kù)的格式可以是 .framework,也能夠是 .a。如果深究的話,.a 文件可以理解為1種歸檔文件,或說(shuō)是緊縮文件。其中存儲(chǔ)的是經(jīng)過(guò)編譯的 .o 格式的目標(biāo)文件。我們可以通過(guò) ar -x 命令來(lái)證明這1點(diǎn):

ar -x libBSStaticLibraryOne.a

解壓結(jié)果

需要提示的1點(diǎn)是,光有 .a 文件還不夠,我們還需要提供頭文件給使用者導(dǎo)入。為了完成這1點(diǎn),我們需要在項(xiàng)目的 Build Phases 中新增1個(gè) Headers Phase,然后把需要對(duì)外暴露的頭文件放到 Public 1欄中:

暴露頭文件

此時(shí)編譯后的頭文件會(huì)放在 .a 文件所在目錄下,usr/local/include 目錄中。

接下來(lái)打開(kāi) OtherLinkerFlag 這個(gè)殼工程,引入 .a 文件和頭文件,運(yùn)行程序,結(jié)果1定是:

-[BSStaticLibraryOne sayOtherThing]: unrecognized selector sent to instance xxx

這就是經(jīng)典的 linker flag 問(wèn)題。首先,我們知道 .a 實(shí)際上是編譯好的目標(biāo)文件的集合,因此問(wèn)題出在鏈接這1步,而非編譯。Objective-C 在使用靜態(tài)庫(kù)時(shí),需要知道哪些文件需要鏈接進(jìn)來(lái),它根據(jù)的就是之前圖中所示的 __.SYMDEF SORTED 文件。

惋惜的是,這個(gè)文件不會(huì)包括所有的 .o 目標(biāo)文件,而只是包括了定義了類(lèi)的目標(biāo)文件。我們可以履行 cat __.SYMDEF\ SORTED 來(lái)驗(yàn)證1下,你會(huì)看到其中并沒(méi)有拓展類(lèi)的信息。這樣1來(lái),BSStaticLibraryOne+Extension.o 雖然存在,但是不被鏈接到終究的可履行文件中,從而致使了找不到方法的毛病。

解決上述問(wèn)題的方法是調(diào)用者在 Build Settings 中找到 other linker flag,并寫(xiě)上 -ObjC 選項(xiàng),這個(gè)選項(xiàng)會(huì)鏈接所有的目標(biāo)文件。但是根據(jù)文檔描寫(xiě),如果靜態(tài)庫(kù)只有分類(lèi),而沒(méi)有類(lèi), 即便加了 -ObjC 選項(xiàng)也會(huì)報(bào)錯(cuò),應(yīng)當(dāng)使用 -force_load 參數(shù)。

由于第3方的代碼使用分類(lèi)幾近是必定事件,因此幾近每一個(gè)使用者都要做如上配置,增加了復(fù)雜度和出錯(cuò)的概率。

除此之外,第3方的代碼很有可能使用了系統(tǒng)的動(dòng)態(tài)庫(kù)。因此使用者還必須手動(dòng)引入這些動(dòng)態(tài)庫(kù)(請(qǐng)記住這1點(diǎn),靜態(tài)庫(kù)不支持遞歸援用,這是個(gè)很麻煩的事情,后面會(huì)介紹),我們以百度地圖 SDK 的集成為例,讀者可以自行對(duì)照手動(dòng)導(dǎo)入和 Cocoapods 集成的步驟區(qū)分: 配置開(kāi)發(fā)環(huán)境iOS SDK。

因此,我總結(jié)的使用 Cocoapods 的好處有以下幾個(gè):

  1. 避免直接導(dǎo)入文件的原始方式,方便后續(xù)代碼升級(jí)
  2. 簡(jiǎn)化、自動(dòng)化集成流程,避免沒(méi)必要要的配置
  3. 自動(dòng)處理庫(kù)的依賴(lài)關(guān)系
  4. 簡(jiǎn)化開(kāi)發(fā)者發(fā)布代碼流程

Cocoapods 工作原理

在我之前的1篇文章: 白話 Ruby 與 DSL 和在 iOS 開(kāi)發(fā)中的應(yīng)用 中簡(jiǎn)單的介紹過(guò),Cocoapods 是用 Ruby 開(kāi)發(fā)的1套工具。每份代碼都是1個(gè) Pod,安裝 Pod 時(shí)首先會(huì)分析庫(kù)的版本和依賴(lài)關(guān)系,這些都是在 Ruby 層面完成的,本文暫且不表。

我們首先假定已找到了要下載的代碼的地址(比如存在 Github 上),從這1步開(kāi)始,接下來(lái)的工作都與 iOS 開(kāi)發(fā)有關(guān)。

如果你手頭有1個(gè) Cocoapods 項(xiàng)目,你應(yīng)當(dāng)會(huì)注意到以下幾個(gè)特點(diǎn):

  1. 主工程中沒(méi)有導(dǎo)入第3方庫(kù)的代碼或靜態(tài)庫(kù)
  2. 主工程不顯式的依賴(lài)各個(gè)第3方庫(kù),但是援用了 libPods.a 這個(gè) Cocoapods 庫(kù)
  3. 不需要手動(dòng)編譯第3方庫(kù),直接運(yùn)行主工程便可,隱式指定了編譯順序

這樣做可以把引入第3方庫(kù)對(duì)主工程釀成的影響降到最低,不過(guò)沒(méi)法完全降為零。比如引入 Cocoapods 以后,項(xiàng)目不能不使用 xworkspace 來(lái)打開(kāi),后面會(huì)介紹緣由。

假定之前的 BSStaticLibraryOne 工程就是下載好的源碼,現(xiàn)在我們要做的就是把它集成到1個(gè)已有的工程,比如叫 ShellProject 中。

我們遇到的第1個(gè)問(wèn)題是,在之前的 demo 中,需要把靜態(tài)庫(kù)和頭文件手動(dòng)拖入到工程中。但這就和 Cocoapods 的效果不1致,畢竟我們希望主工程完全不受影響。

靜態(tài)庫(kù)和頭文件導(dǎo)入

如果我們甚么都不做,固然不可能在殼工程中援用另外一個(gè)項(xiàng)目下的靜態(tài)庫(kù)和頭文件。但這個(gè)問(wèn)題也能夠換個(gè)方式問(wèn):“Xcode 怎樣知道它們可以援用,還是不可以援用呢?”,答案在于 Build Settings 里面的 Search Paths 這1節(jié)。默許情況下,Header Search PathLibrary Search Path 都是空的,也就是說(shuō) Xcode 不會(huì)去任何目錄下找靜態(tài)庫(kù)和頭文件,除非他們被人為的導(dǎo)入到工程中來(lái)。

因此,只要對(duì)上述兩個(gè)選項(xiàng)的值略作修改, Xcode 就能夠辨認(rèn)了。我們目前的項(xiàng)目結(jié)構(gòu)以下所示:

- CocoaPodsDemo(根目錄)
    - BSStaticLibraryOne (被援用的靜態(tài)庫(kù))
        - Build/Products/Debug-iphonesimulator (編譯結(jié)果的目錄)
            - libBSStaticLibraryOne.a  (靜態(tài)庫(kù))
            - usr/local/include (頭文件目錄)
                - BSStaticLibraryOne.h
                - BSStaticLibraryOne+Extension.h
    - ShellProject (殼工程)

因此我們要做的是讓殼工程的 Library Search Path 指向 CocoaPodsDemo/BSStaticLibraryOne/Build/Products/Debug-iphonesimulator 這個(gè)目錄:

Library Search Path = $PROJECT_DIR/../BSStaticLibraryOne/Build/Products/Debug-iphonesimulator/

這里記得寫(xiě)相對(duì)路徑,Xcode 會(huì)自動(dòng)轉(zhuǎn)成絕對(duì)路徑。然后 Header Search Path 也依樣畫(huà)葫蘆:

Header Search Path = $PROJECT_DIR/../BSStaticLibraryOne/Build/Products/Debug-iphonesimulator/LibOne

仔細(xì)的讀者或許會(huì)發(fā)現(xiàn), LibOne 這個(gè)文件夾完全不存在。是這樣的,由于我覺(jué)得 usr/local/include 這個(gè)路徑太深,太丑,所以可以在靜態(tài)庫(kù)的項(xiàng)目配置中,在 Packaging 這1節(jié)中,找到 Public Headers Folder Path,將它的值從 usr/local/include 修改成 LibOne,然后重新編譯,這時(shí)候就會(huì)看到生成的頭文件位置產(chǎn)生了變化。

固然,這時(shí)候候還是沒(méi)法直接援用靜態(tài)庫(kù)的。由于我們只是告知 Xcode 可以去對(duì)應(yīng)路徑去找,但并沒(méi)有明確聲明要用,所以需要在 Other Linker Flags 中添加1個(gè)選項(xiàng): -l"BSStaticLibraryOne",引號(hào)中的內(nèi)容就是靜態(tài)庫(kù)的工程名。

需要提示的是, 靜態(tài)庫(kù)編譯出來(lái)的 .a 文件會(huì)被手動(dòng)加上 lib 前綴,在寫(xiě)入到 Other Linker Flags 的時(shí)候千萬(wàn)要注意去掉這個(gè)前綴,否則就會(huì)出現(xiàn) Library not found 的毛病。

配置好以后的工程以下圖所示:

配置搜索路徑

現(xiàn)在項(xiàng)目中沒(méi)有任何第3方的庫(kù)或代碼,仍然可以正常援用第3方的類(lèi)并運(yùn)行成功。

援用多個(gè)第3方庫(kù)

當(dāng)我們的項(xiàng)目需要援用多個(gè)第3方庫(kù)的時(shí)候,就有兩種思路:

  1. 每份第3方代碼作為1個(gè)工程,分別打出1個(gè)靜態(tài)庫(kù)和頭文件。
  2. 所有第3方代碼放在同1個(gè)工程中,建立多個(gè) target,每一個(gè) target 對(duì)應(yīng)1個(gè)靜態(tài)庫(kù)。

從直覺(jué)來(lái)看,第2種組織方式看上去更加集中,易于管理。斟酌后面我們還要解決庫(kù)的依賴(lài)問(wèn)題,而且項(xiàng)目?jī)?nèi)的依賴(lài)處理比 workspace 中的依賴(lài)處理要容易很多(后面會(huì)介紹到),所以第2種組織方式更具有可行性。

如果讀者手頭有使用了 Cocoapods 的項(xiàng)目,可以看到它的文件組織結(jié)構(gòu)以下:

- ShellProject(根目錄,殼工程)
    - ShellProject (項(xiàng)目代碼)
    - ShellProject.xcodeproj (項(xiàng)目文件)
    - Pods (第3方庫(kù)的根目錄)
        - Pods.xcodeproj (第3方庫(kù)的總工程)
        - AFNetworking (某個(gè)第3方庫(kù))
        - Mantle (另外一個(gè)第3方庫(kù))
        - ……

而在我的 demo 中,為了偷懶,沒(méi)有把第3方庫(kù)放在殼工程目錄下,而是選擇和它平級(jí)。這其實(shí)沒(méi)有太大的區(qū)分,只是援用路徑不同而已,不用太關(guān)心。我們現(xiàn)在摹擬添加1個(gè)新的第3方庫(kù),完成后的代碼結(jié)構(gòu)以下:

- CocoaPodsDemo(根目錄)
    - BSStaticLibraryOne (第3方庫(kù)總的文件夾,相當(dāng)于 Pods,由于偷懶,名字就不改了)
        - BSStaticLibraryOne (第1個(gè)第3方庫(kù))
        - BSStaticLibraryTwo (新增1個(gè)第3方庫(kù))
        - BSStaticLibraryOne.xcodeproj (第3方庫(kù)的項(xiàng)目文件)
        - Build/Products/Debug-iphonesimulator (編譯結(jié)果的目錄)
    - ShellProject (殼工程)

首先要新建1個(gè)文件夾 BSStaticLibraryTwo 并拖入到項(xiàng)目中,然后新增1個(gè) Target(以下圖所示)。

新增 target

在 Xcode 工程中,我們都接觸過(guò) Project。打開(kāi) .xcodeproj 文件就是打開(kāi)1個(gè)項(xiàng)目(Project)。Project 負(fù)責(zé)的是項(xiàng)目代碼管理。1個(gè) Project 可以有多個(gè) Target,這些 target 可使用不同的文件,最后也就能夠得出不同的編譯產(chǎn)物。

通過(guò)使用多個(gè) target,我們可以用少量不同的代碼得到不同的 app,從而避免了開(kāi)多個(gè)工程的必要。不過(guò)我們這里的幾個(gè) target 其實(shí)不含有相同代碼,而是1個(gè)第3方庫(kù)對(duì)應(yīng)1個(gè) target。

接下來(lái)我們新建1個(gè)類(lèi),記得要加入到 BSStaticLibraryTwo 這個(gè) target 下,記得和之前1樣修改 Public Headers Folder Path 并添加1個(gè) Build Phase

代碼添加到另一個(gè) Target

在左上角將 Scheme 選擇為 BSStaticLibraryTwo 再編譯,可以看到新的靜態(tài)庫(kù)已生成了。

項(xiàng)目?jī)?nèi)依賴(lài)

對(duì)主工程來(lái)講,必須在子工程(第3方庫(kù))編譯完后才開(kāi)始編譯,或換句話說(shuō),我們?cè)谥鞴こ讨邪聪?Command + R/B 時(shí),所有子工程必須先被編譯。對(duì)這類(lèi)跨工程的庫(kù)依賴(lài),我們沒(méi)法直接指明依賴(lài)關(guān)系,必須隱式的設(shè)置依賴(lài)關(guān)系,我們還是以 Cocoapods 工程舉例:

跨工程依賴(lài)

主工程中用到了 libPod.a 這個(gè)靜態(tài)庫(kù),而且它其實(shí)不是在主工程中生成,而是在 Pods 這個(gè)項(xiàng)目中編譯生成。1旦存在這類(lèi)援用關(guān)系,那末也就建立了隱式的依賴(lài)關(guān)系。在編譯主工程時(shí),Xcode 會(huì)確保它援用的所有靜態(tài)庫(kù)都先被編譯。

之前我們討論過(guò)兩種管理多個(gè)靜態(tài)庫(kù)的方法,如果選擇第1種方法, 每一個(gè)靜態(tài)庫(kù)對(duì)應(yīng)1個(gè) Xcode 項(xiàng)目,雖然不是不可以,但主工程看上去就就會(huì)比較復(fù)雜,這主要是跨項(xiàng)目依賴(lài)致使的。

而在項(xiàng)目?jī)?nèi)部管理 target 的依賴(lài)相對(duì)而言就簡(jiǎn)單很多了。我們只要新建1個(gè)總的 target,無(wú)妨也叫作 Pod。它甚么也不做,只需要依賴(lài)另外兩個(gè)靜態(tài)庫(kù)就能夠了,設(shè)置 Target Dependencies:

此時(shí)選擇 Pod 這個(gè) target 編譯,另外兩個(gè)靜態(tài)庫(kù)也會(huì)被編譯。因此接下來(lái)的任務(wù)就是讓主工程直接依賴(lài)于 Pod 這個(gè) target,自然也就間接依賴(lài)于真正有用的各個(gè)第3方靜態(tài)庫(kù)了。

接下來(lái)我們重復(fù)之前的步驟,設(shè)置好頭文件和靜態(tài)庫(kù)的搜索路徑,并在 Other Linker Flags 里面添加: -l"BSStaticLibraryTwo",就能夠使用第2個(gè)靜態(tài)庫(kù)了。

Workspace

到目前為止,我們摹擬了多個(gè)靜態(tài)庫(kù)的組織,和如何在主工程中援用他們。不過(guò)還存在1些小瑕疵,我截了 Xcode 中的1幅圖:

Xcode 識(shí)別有問(wèn)題

從圖中可以很明顯的發(fā)現(xiàn): 第3方庫(kù)中的代碼被認(rèn)為是系統(tǒng)代碼,色彩為藍(lán)色。而正常的自定義方法應(yīng)當(dāng)綠色,會(huì)對(duì)開(kāi)發(fā)者造成困擾。

除這個(gè)小瑕疵之外,在之前談到的跨項(xiàng)目依賴(lài)中,1個(gè)項(xiàng)目不單單需要援用另外一個(gè)項(xiàng)目的產(chǎn)物,還有1個(gè)先決條件: 把這兩個(gè)項(xiàng)目放入同1個(gè) Workspace 中。Workspace 的作用是組織多個(gè) Project,使得各個(gè) Project 直接可以有援用依賴(lài)關(guān)系,同時(shí)也能讓 Xcode 辨認(rèn)出各個(gè) Project 中的代碼和頭文件。

按住 Command + Control + N 可以新建1個(gè) Workspace:

新建 Workspace

完成以后就會(huì)看到1個(gè)完全空白的項(xiàng)目,在左邊按下右鍵,選擇 Add Files to:

添加文件

然后選中靜態(tài)庫(kù)項(xiàng)目和主工程的 .xcodeproj 文件,把這兩個(gè)工程都加進(jìn)來(lái):

需要提示的是,切換到 Workspace 以后, Xcode 會(huì)把 Workspace 所在目錄當(dāng)作項(xiàng)目根目錄,因此靜態(tài)庫(kù)的編譯結(jié)果會(huì)放在 /CocoaPodsDemo/Build/Products/…,而不再是之前的 /CocoaPodsDemo/BSStaticLibraryOne/Build/Products/…,因此需要手動(dòng)對(duì)主工程中的搜索路徑做1下調(diào)劑。

做好上述改動(dòng)后,即便我們刪除掉 BSStaticLibraryOne 這個(gè)項(xiàng)目的編譯結(jié)果,只在 Workspace 中編譯主項(xiàng)目,Xcode 也會(huì)自動(dòng)為我們編譯被依賴(lài)的靜態(tài)庫(kù)。這就是為何我們只需要履行 pod install 下載好代碼,就能夠不用做別的操作,直接在主項(xiàng)目中運(yùn)行。

固然,代碼色彩毛病的小問(wèn)題也在 Workspace 恢復(fù)正常了。

靜態(tài)庫(kù)嵌套

到這里,基本上關(guān)于 Cocoapods 的工作原理就算是分析完了。上述操作除文件增加,基本上都是修改 .pbxproj 文件。所有的 Xcode 都會(huì)在該文件中得到反應(yīng),同理,只要修改該文件,也能到達(dá)上述手動(dòng)操作的效果。而 Cocoapods 開(kāi)發(fā)了1套 Ruby 工具,用來(lái)封裝這些修改,從而實(shí)現(xiàn)了自動(dòng)化。

文章開(kāi)頭,我們提到作為代碼提供者,如果自己的代碼還援用別的第3方庫(kù),那末提供代碼會(huì)變得很麻煩,這主要是由于靜態(tài)庫(kù)不會(huì)遞歸援用致使的。我們已知道靜態(tài)庫(kù)其實(shí)就是1堆編譯好的目標(biāo)文件(.o 文件)的打包情勢(shì),它需要配合頭文件來(lái)使用。所謂的不會(huì)遞歸援用是指,假定項(xiàng)目 A 援用了靜態(tài)庫(kù) B(或是動(dòng)態(tài)庫(kù),也是1樣),那末 A 編譯后得到的靜態(tài)庫(kù)中,其實(shí)不含有靜態(tài)庫(kù) B 的目標(biāo)文件。如果有人拿到這樣的靜態(tài)庫(kù) A,就必須補(bǔ)齊靜態(tài)庫(kù) B,否則就會(huì)遇到 “Undefined symbol” 毛病。

如果我們提供的代碼援用了系統(tǒng)的動(dòng)態(tài)庫(kù),問(wèn)題還比較簡(jiǎn)單,只要在文檔里面注明,讓使用者自己導(dǎo)入便可。但如果是第3方代碼,那末這簡(jiǎn)直是1起災(zāi)害。即便使用者找到了提供者使用的靜態(tài)庫(kù),那個(gè)靜態(tài)庫(kù)也很有可能已進(jìn)行了升級(jí),而版本不1致的靜態(tài)庫(kù)可能具有完全不同的 API。也就是說(shuō)代碼提供者還要在文檔中注明使用的靜態(tài)庫(kù)的版本,然后由使用者去找到這個(gè)版本。我想,這才是 Cocoapods 真正致力于解決的任務(wù)。

CocoaPods 的做法比較簡(jiǎn)單,由于他有1套統(tǒng)1的版本表示規(guī)則,也能夠自動(dòng)分析依賴(lài)關(guān)系,而且每一個(gè)版本的代碼都有記錄。后面會(huì)介紹 Cocoapods 的相干實(shí)踐,這里我們先思考1下如何手動(dòng)解決靜態(tài)庫(kù)嵌套的問(wèn)題。

既然靜態(tài)庫(kù)只是目標(biāo)文件的打包情勢(shì),那末我只需要找到被嵌套的靜態(tài)庫(kù),拿到其中的目標(biāo)文件,然后和外層的靜態(tài)庫(kù)放在1起重新打包便可。這個(gè)進(jìn)程比較簡(jiǎn)單, 我也就沒(méi)有做 demo,用代碼應(yīng)當(dāng)就能夠說(shuō)明得很清楚。假定我們有靜態(tài)庫(kù) A.a 和 B.a,其中 A 需要援用 B,現(xiàn)在我希望對(duì)外發(fā)布 A,并且集成 B:

lipo A.a -thin x86_64 output A_64.a # 如果是多 CPU 架構(gòu),先提取出某1種架構(gòu)下的 .a 文件
lipo B.a -thin x86_64 output B_64.a
ar -x A_64.a # 解壓 A 中的目標(biāo)文件
ar -x B_64.a # 解壓 B 中的目標(biāo)文件
libtool -static -o Together.a *.o # 把所有 .o 文件1起打包到 Together.a

這時(shí)候候 Together.a 文件就能夠當(dāng)作完全版的靜態(tài)庫(kù) A 給他人使用了。

Cocoapods 使用

本來(lái) Cocoapods 的使用就比較簡(jiǎn)單。特別是了解完原理后,使用起來(lái)應(yīng)當(dāng)更加得心應(yīng)手了,對(duì)1些常見(jiàn)的毛病也有了分析能力。不過(guò)有個(gè)小細(xì)節(jié)還是需要注意1下:

Podfile.lock

關(guān)于 Cocoapods 文件是不是要加入版本控制并沒(méi)有明確的答案。我之前的習(xí)慣是不加入版本控制。由于這樣會(huì)讓提交歷史明顯變得復(fù)雜,如果不同分支上使用的不同版本的 pod,在合并分支時(shí)就會(huì)出現(xiàn)大量沖突。

但是官方的推薦是把它加入到版本控制中去。這樣他人不再需要履行 pod install,而且能夠確保所有人的代碼1定1致。

但是雖然不強(qiáng)迫把全部 Pod 都加入版本控制,但是 Podfile.lock 不管如何必須添加到版本控制系統(tǒng)中。為了解釋這個(gè)問(wèn)題,我們先來(lái)看看 Cocoapods 可能存在的問(wèn)題。

假定我們?cè)?Podfile 中寫(xiě)上: pod 'AFNetWorking',那末默許是安裝 AFNetworking 的最新代碼。這就致使用戶 A 可能裝的是 3.0 版本,而用戶 B 再安裝就變成了 4.0 版本。即便我們?cè)?Podfile 中指定了庫(kù)的具體版本,那也不能保證不出問(wèn)題。由于1個(gè)第3方庫(kù)還有可能依賴(lài)其他的第3方庫(kù),而且不保證它的依賴(lài)關(guān)系是具體到版本號(hào)的。

因此 Podfile.lock 存在的意義是將某1次 pod install 時(shí)使用的各個(gè)庫(kù)的版本,和這個(gè)庫(kù)依賴(lài)的其他第3方庫(kù)的版本記錄下來(lái),以供他人使用。這樣1來(lái),pod install 的流程實(shí)際上是:

  1. 判斷 Podfile.lock 是不是存在,如果不存在,依照 Podfile 中指定的版本安裝
  2. 如果 Podfile.lock 存在,檢查 Podfile 中每個(gè) Pod 在 Podfile.lock 中是不是存在
  3. 如果存在, 則疏忽 Podfile 中的配置,使用 Podfile.lock 中的配置(實(shí)際上就是甚么都不做)
  4. 如果不存在,則使用 Podfile 中的配置,并寫(xiě)入 Podfile.lock 中

而另外一個(gè)經(jīng)常使用命令 pod update 其實(shí)不是1個(gè)平常更新命令。它的原理是疏忽 Podfile.lock 文件,完全使用 Podfile 中的配置,并且更新 Podfile.lock。1旦決定使用 pod update,就必須所有團(tuán)隊(duì)成員1起更新。因此在使用 update 前請(qǐng)務(wù)必了解其背后產(chǎn)生的事情和對(duì)團(tuán)隊(duì)釀成的影響,并且確保有必要這么做。

發(fā)布自己的 Pod

很多教程都有介紹開(kāi)源 Pod 的流程,我在實(shí)踐的時(shí)候主要參考了以下兩篇文章。相對(duì)來(lái)講比較詳細(xì),條理清晰,也推薦給大家:

  1. Cocoapods系列教程(2)——開(kāi)源主義接班人
  2. Cocoapods系列教程(3)——私有庫(kù)管理和模塊化管理

如果要?jiǎng)?chuàng)建公司內(nèi)部的私有庫(kù),首先要建立1個(gè)自己的倉(cāng)庫(kù),這個(gè)倉(cāng)庫(kù)在本地也會(huì)有存儲(chǔ):

倉(cāng)庫(kù)

如圖中所示,master 是官方倉(cāng)庫(kù),而 baidu 則是我用來(lái)測(cè)試的私有倉(cāng)庫(kù)。倉(cāng)庫(kù)中會(huì)存有所有 Pod 的信息,每一個(gè)文件夾下都依照版本號(hào)做了辨別,每一個(gè)版本對(duì)應(yīng)1個(gè) podspec 文件。從圖中可以看到,cocoapods 會(huì)緩存所有的 podspec 到本地,但不會(huì)緩存每一個(gè) Pod 的具體代碼。每當(dāng)我們履行 pod install 時(shí),都會(huì)先從本地查找 podspec 緩存是不是存在,如果不存在則會(huì)去中央倉(cāng)庫(kù)下載。

我們常常遇到的 pod install 很慢就是由于默許情況下會(huì)更新全部 master。此時(shí) master 不單單存儲(chǔ)著本地使用 Pod 的 PodSpec 文件,而是存儲(chǔ)了所有的已有的 Pod。所以這個(gè)更新進(jìn)程看起來(lái)異常緩慢。有些解決方案是使用:

pod install --verbose --no-repo-update

這實(shí)際上是治標(biāo)不治本的遷就醫(yī)治方法,由于本地的倉(cāng)庫(kù)早晚要被更新,否則就拿不到最新的 PodSpec。要想完全解決這1問(wèn)題,除定期更新外,還可以選擇其他速度較快的鏡像倉(cāng)庫(kù)。

podspec 文件是我們開(kāi)源 Pod 時(shí)需要填寫(xiě)的文件,主要是描寫(xiě)了 Pod 的基礎(chǔ)信息。除1些無(wú)關(guān)緊要的配置和介紹信息外,最重要的填寫(xiě) source_filesdependency。前者用來(lái)規(guī)定哪些文件會(huì)對(duì)外公布,后者則指定此 Pod 依賴(lài)于哪些其他 Pod。比如在上圖中,我的 PrivatePod 就依賴(lài)于 CorePod,在公司內(nèi)部的項(xiàng)目中使用 PodS 依賴(lài)可以大量簡(jiǎn)化代碼的集成流程。1個(gè)典型的 PodSpec 可能長(zhǎng)這樣:

填寫(xiě)好上述信息后,我們只要先 lint 1下 podspec,確保格式無(wú)誤,就能夠提交了。

生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 久久91综合国产91久久精品 | 亚洲一区二区三区在线网站 | 亚洲国产国产综合一区首页 | 在线成人免费观看国产精品 | 亚洲视频在线观看网址 | a毛片免费看 | 激情爱爱网站 | 综合爱爱网 | 免费看黄色的网站 | 2021国产成人午夜精品 | 网友自拍网站 | 欧美羞羞| 麻豆高清视频在线观看 | 女人18毛片a级18毛多水真多 | 亚洲免费视频播放 | 宇都宫紫苑99av | 在线看的黄色网址 | 日韩手机在线观看 | 欲色综合| 日日摸人人看97人人澡 | 欧美疯狂 | 日韩精品亚洲精品485页 | 亚洲日韩欧美综合 | 国产精品福利视频一区二区三区 | 白嫩美女一级毛片免费看 | 欧美成人黑人xx视频免费观看 | 欧美特级特黄a大片免费 | 吃奶japanesevideo| 久久免费精品国产72精品剧情 | qvod小说区图片区亚洲 | 日韩欧美爱爱 | 欧美xxxx性高清 | 成人免费小视频 | 久久精品免观看国产成人 | 国产天堂网 | 亚洲国产成人99精品激情在线 | 欧美成人 综合网播九公社 欧美成人18 | 性xxxxfreexxxxvideo| 欧美在线一二三区 | 午夜影院免费体验 | 尤物精品|