雖然蘋果今年推出了 DocC 這套新的文件產生工具,不過,DocC 只能夠用在 Swift 上,短時間之內,在開發 Framework 時,還是很有可能得用到 Objective-C,或是你手上有一些過去用 Objective-C 寫的 Framework;於是,在工作上,大概還是得用 jazzy 來產生文件。
Jazzy 可以用來產生 Swift 與 Objective-C 的文件,相較於產生 Swift 文件,在 Objective-C 方面限制卻多少不少。在產生 Objective-C 文件的時候,首先必須要指定一個 umbrella header,然後利用這個 umbrella header 中 include 了哪些其他 header,找到整個 framework 中有全部哪些 API。而在尋找 header 的過程中,又要求所有其他的 header,必須要在 umbrella header 的同一層目錄中。Jazzy 的 issue tracker 中,也可以看到有人反應這個問題。
如果你手上的專案稍微大一點,大概沒辦法忍受專案中所有的 header 都在同一層目錄下,或多或少會把各種不同性質的 class,分類放在不同的目錄下,如此一來,你在呼叫 jazzy 的時候,jazzy 就找不到這些 header。我們可以稍微繞個圈解決這個問題:先用 xcodebuild 指令把 framework 編譯出來,再把 jazzy 要去尋找的 umbrella header,指定到編譯出來的 framework 的 Headers 目錄下–不管你原來專案怎麼擺放檔案,反正在編譯之後,所有的 header 檔案,最後都會擺在一起。
所以 build script 可能會像這樣:
而我其實遇到的狀況是,我其實要發行兩個 Objective-C framework,而第二個 framework 相依於第一個 framework。具體來說,我有 MyFrameworkA 與 MyFrameworkB,MyFrameworkB 使用了 MyFrameworkA 裡頭的東西,所以在 MyFrameworkB 中,有一些 header 中,會出現 #include <MyFrameworkA/MyFramework.h> ,如果沒有正確設定的話,jazzy 在產生 MyFrameworkB 的文件時,就會告訴你它找不到 MyFrameWorkA.h 而直接失敗。
要讓 jazzy 可以正確同時找到這兩個 framework 的 header,我們應該先建立一個目錄,然後把 MyFrameworkA 與 MyFrameworkB 的 header,都放在這個目錄的子目錄下,然後把 jazzy 的 framework root 目錄設到上層。
大概是這樣的目錄結構
在同一個 script 中,我們繼續寫 FrameworkB 的部份:
由於兩個 framework 的 header 都放在 ${BUILD_DIR}/headers/ 下,所以就可以參照到另外一個 framework 的 header;但這麼做,也會讓 jazzy 以為要把 FrameworkA 的文件也一起產生出來。
所以,我們最後用 exclude 語法,把 FrameworkA 排除掉,避免產生不需要的文件。