iOS封裝功能生成 .framework

前言

? ? ? 如果你想將你開發(fā)的控件與別人分享悼尾,一種方法是直接提供源代碼文件傻铣。然而章贞,這種方法并不是很優(yōu)雅。它會暴露所有的實現(xiàn)細節(jié)非洲,而這些實現(xiàn)你可能并不想開源出來鸭限。此外,開發(fā)者也可能并不想看到你的所有代碼两踏,因為他們可能僅僅希望將你的這份漂亮代碼的一部分植入自己的應(yīng)用中败京。

? ? ? 另一種方法是將你的代碼編譯成靜態(tài)庫(library),讓其他開發(fā)者添加到自己的項目中梦染。然而赡麦,這需要你一并公布所有的公開的頭文件,實在是非常不方便帕识。

你需要一種簡單的方法來編譯你的代碼泛粹,這種方法應(yīng)該使得你的代碼易分享,并且在多個工程中易復(fù)用肮疗。你需要的是一種方法來打包你的靜態(tài)庫晶姊,將所有的頭文件放到一個單元中,這樣你就可以立刻將其加入到你的項目中并使用伪货。

? ? ? OS X完美地支持這一點帽借,因為Xcode就提供了一個項目模板,包含著默認構(gòu)建目標(target)和可以容納類似于圖片超歌、聲音、字體等資源的文件蒂教。你可以為iOS創(chuàng)建Framework巍举,不過這是一個比較復(fù)雜的手工活,如果你跟著教程走凝垛,你將學(xué)到怎么樣跨過路障懊悯,順利地完成Framework的創(chuàng)建。

比較

可以參考這篇文章.a和.framework.a和.framework的區(qū)別梦皮。

我們可以看出.a的封裝和.framework的封裝差不多炭分,也有模擬器和真機合并的過程,通過上邊的圖片我們可以看出.a 和.framework的區(qū)別剑肯,就是.a+.h+soureFile=.framework捧毛。可以看出我們直接封裝.framework其實是最好的。那么我們就來看看framework怎么封裝的呀忧。

另外關(guān)于.a的封裝大家可以參考iOS如何生成.a文件

目標

? ? ? 本文將基于Xcode7創(chuàng)建一個簡單的工程师痕,通過兩種方法來教大家如何制作一個自己的framework,目的就是簡單易學(xué)的制作framework而账。這種方法可以使得你的代碼易分享胰坟,在多個工程中復(fù)用,并且可以隱藏實現(xiàn)細節(jié)泞辐,控制公開的頭文件笔横。

步驟

1、打開Xcode咐吼,新建工程吹缔。

不要選擇“Application”,選擇“Framework & Library”汽烦。選擇第一個涛菠,然后Next。

2撇吞、創(chuàng)建功能類俗冻。

這里我創(chuàng)建一個繼承自NSObject的SayHello類

3、實現(xiàn)功能牍颈。

在新創(chuàng)建的類里面聲明方法并實現(xiàn)迄薄。這里我寫一個sayHello的方法,以便后面測試使用煮岁。

4讥蔽、更改參數(shù)

在TARGETS下選中工程,在Build Settings下更改幾個參數(shù)画机。

5冶伞、增加armv7s

? 在Architectures下增加armv7s,并選中步氏。將Build Active Architecture Only 設(shè)置為NO响禽。

6、設(shè)置Headers

將你要公開的頭文件拖至Public下荚醒,要隱藏的放在Private或者Project下芋类,當(dāng)然,隱藏的頭文件就無法再被引用界阁。

然后需要在Test.h(必須是公開的侯繁,否則無法引用)中將你所有要公開的.h引入。



打包Framework

第一種方法

1.選中模擬器泡躯,編譯程序

2.選中測試機贮竟,編譯程序

3.在finder中找到framework文件

選中圖中所標示的framework丽焊,然后右鍵show in finder。

找到下圖中所示的Test文件坝锰,一個是Debug-iphoneos(真機)下的粹懒,一個是Debug-iphonesimulator(模擬器)下的。

4.通過終端命令將兩個framework合為一個模擬器和真機都可使用的framework顷级。

打開控制臺輸入 lipo -create iphoneos下frameworkTest的路徑 simulator下frameworkTest的路徑 -output 新的路徑凫乖,這樣就完成了模擬器和真機版本的合并,新路徑下的frameworkTest就是你合并后的文件弓颈,將這個文件名字改成和你未合并之前的Test一樣的名字帽芽,放到framework文件夾下,替換掉原來的frameworkTest文件翔冀。

上邊說的亂糟糟的导街,看不清楚,這里給大家解釋一下纤子,看下邊的圖:打開終端搬瑰,手動輸入畫紅線的lipo -create命令铅搓,然后綠線是iphoneos下frameworkTest的路徑(找到iphoneos下frameworkTest的文件哪痰,拖拽進來),會自動有空格该面,紫線是simulator下frameworkTest的路徑(同樣找到simulator下frameworkTest的文件卡乾,拖拽進來)翼悴,也會自動有空格,然后輸入-output幔妨,然后敲空格鹦赎,在引入一個新的路徑(拖拽進一個新的路徑),最后敲回車误堡。這樣就完成合并了古话。

上面這段命令就是把真機和模擬器的frameworkTest合并成一個MyNewFrameworktest文件并存放在桌面上的New文件夾下。

這里我們合并的時候會遇到一個error锁施,這是啥原因還真不知道煞额,但是會在和我們-output的文件夾路徑并列的地方生成一個.lipo文件,這個.lipo文件我們下邊會說到沾谜。

注意:合并完成后會出現(xiàn)一個如下圖的.lipo格式的文件。

這TM是啥胀莹,不是應(yīng)該出現(xiàn)一個類似下圖的嗎基跑?不應(yīng)該后綴什么也沒有嗎?怎么后綴會是.lipo描焰,這是什么文件跋狈瘛栅螟?!

我們的操作是按照人家說的把合成后的文件名字改成MyFrameworkTest替換原來的篱竭。而且力图,把后綴.lipo去掉!

在按照上述說的掺逼,替換了原來的吃媒。

然后就可以進行下一步了。

5.將修改后的framework拷貝出來保存吕喘,這就是我們最終制作的framework赘那。

第二種方法

1、選中TARGETS下的工程氯质,點擊上方的Editor,選擇Add Target創(chuàng)建一個Aggregate.

2募舟、選擇Other下的Aggregate,點擊Next創(chuàng)建闻察。

3拱礁、嵌入腳本。選中剛剛創(chuàng)建的Aggregate,然后選中右側(cè)的Build Phases,點擊左下方加號辕漂,選擇New Run Script Phase

將這段腳本復(fù)制進去:

# Sets the target folders and the finalframework product.# 如果工程名稱和Framework的Target名稱不一樣的話呢灶,要自定義FMKNAME# 例如: FMK_NAME = "MyFramework"FMK_NAME=${PROJECT_NAME}# Install dir will be the final output tothe framework.# The following line create it in the rootfolder of the current project.? INSTALL_DIR=${SRCROOT}/Products/$? ? ? {FMK_NAME}.framework# Working dir will be deleted after theframework creation.? WRK_DIR=build? DEVICE_DIR=${WRK_DIR}/Release-iphoneos/$? ? ? ? ? ? ? ? ? ? ? ? {FMK_NAME}.framework? SIMULATOR_DIR=${WRK_DIR}/Release-? iphonesimulator/${FMK_NAME}.framework# -configuration ${CONFIGURATION}# Clean and Building both architectures.xcodebuild -configuration"Release"-target"${FMK_NAME}"-sdk iphoneos clean build? xcodebuild -configuration"Release"-target"${FMK_NAME}"-sdk iphonesimulator clean? ? ? ? ? build# Cleaning the oldest.if[-d"${INSTALL_DIR}"]thenrm -rf"${INSTALL_DIR}"fimkdir -p"${INSTALL_DIR}"cp -R"${DEVICE_DIR}/""${INSTALL_DIR}/"# Uses the Lipo Tool to merge both binaryfiles (i386 + armv6/armv7) into one? ? ? Universal final product.? lipo -create"${DEVICE_DIR}/${FMK_NAME}""${SIMULATOR_DIR}/${FMK_NAME}"-output"$? ? ? ? ? ? ? ? ? ? ? {INSTALL_DIR}/${FMK_NAME}"rm -r"${WRK_DIR}"open"${INSTALL_DIR}"

這里有一個誤區(qū),就是復(fù)制上邊的這段腳本的時候钮热,會在我們期望的效果里面多了幾個回車填抬,這幾個回車是致命的,如果不刪除回車隧期,會報出如下的錯誤:

最后的格式如下圖飒责,盡量一個回車也不能錯:

通過第一種方法中“把真機和模擬器的frameworkTest合并成一個”的過程和上邊的腳本語言比較,我們可以發(fā)現(xiàn)其實兩者異路同歸仆潮,兩個方法里面同時用到了“l(fā)ipo -create ?xxx”和“-output xxx”宏蛉,不同的地方是第一種方法需要我們自己真機和模擬器分別變異一遍,而且需要我們把framework的路徑拖進去性置,相比而言第二種方法比較簡單拾并。

4、編譯鹏浅。如圖所示嗅义,command+B編譯。這里Generic iOS Device的意思是“iOS通用設(shè)備”隐砸,大概就是說模擬器和真機都能用之碗。

5、編譯成功后會自動跳出一個finder季希,保存這個.framework褪那,這就是我們需要的framework幽纷。

至此,兩種打包framework的方法介紹完成博敬!



最后就是用我們的Framework了友浸,倒入另一個Xcode中,我們打開這個framework看看偏窝,發(fā)現(xiàn)只有Headers收恢,里面有兩個.h,其中一個是我們之前添加的FrameworkDemo.h文件囚枪,另一個就是我們的SayHello.h 派诬。

然后引入頭文件:

由于我們測試的方法是實例方法,那么我們實例化一個實例對象链沼,然后就可以讓這個實例對象調(diào)取相應(yīng)的方法了:

至此默赂,完成Framework的制作和使用。


總結(jié)

最后需要注意的是:

1括勺、.h文件的外漏一定要保證是自己的想要外漏的缆八。不想外漏的就別外漏了。

2疾捍、開始打包的時候奈辰,一定要在選中模擬器和選中真機上邊分別編譯一次, 我覺得之前在家里沒有真機的時候編譯的好像不對乱豆。

3奖恰、在終端上邊合并的時候可能是error并生成一個.lipo文件,不要怕宛裕,大膽修改成同名的不掛后綴的同名文件瑟啃。

4、調(diào)用的時候分清楚是類方法還是實例方法揩尸,方便調(diào)用蛹屿。

5、在制作framework或者lib的時候岩榆,如果使用了category错负,則使用改FMWK的程序運行時會crash,此時需要在該工程中 other linker flags添加兩個參數(shù) -ObjC -all_load勇边。(這點沒有親測)

6犹撒、帶有圖片資源的需要把圖片打包成Bundle文件,和framework一起拷貝到相應(yīng)的項目中粒褒。

7识颊、公開的類中如果引用的private的類,打包以后對外會報錯怀浆,找不到那個private的類谊囚,可以把那個private的.h放到(也沒親測)

8、namespace 沖突执赡。靜態(tài)庫用了某第三方庫镰踏,項目也用了同樣的第三方庫,在編譯的時候就會有 duplicate symbol 錯誤沙合,因為有兩份同樣的第三方庫奠伪。解決辦法就是把用到的第三方庫加上自定義前綴,包括類名首懈、delegate 協(xié)議绊率、常量名,尤其需要注意 Category 的方法名要修改究履。

9滤否、封裝靜態(tài)庫的時候應(yīng)盡量避免引入重量級第三方庫,多自己進行封裝最仑。

10藐俺、一個靜態(tài)庫要有自己獨有的前綴,所有類名泥彤、常量等都要加同樣的前綴欲芹。

11、真機+模擬器支持吟吝。(和第2條意思一樣)Xcode 默認只會用當(dāng)前環(huán)境(真機或模擬器)生成靜態(tài)庫菱父,這樣的 SDK 不方便其他項目開發(fā)時調(diào)試。解決辦法就是通過腳本生成一份通用庫剑逃,build_universal_library.sh浙宜,via SO.

12、文檔炕贵。靜態(tài)庫的方便是使用者直接拿你提供的方法來用梆奈,無需關(guān)注具體實現(xiàn);不方便在于看不到實現(xiàn)称开,出現(xiàn)問題無法排查亩钟,因此需要把 SDK 的版本、更新歷史鳖轰、使用清酥、FAQ 等寫成文檔,方便使用蕴侣,也顯得 SDK 比較正式規(guī)范焰轻。

13、圖片等資源文件用 bundle 方式打包昆雀。一個簡單制作 bundle 的方法:新建文件夾辱志,重命名為 YourSDK.bundle蝠筑,然后 Show Package Contents 打開,加入圖片揩懒。使用圖片的時候需要指明 bundle: [UIImage imageNamed:@"YourSDK.bundle/img.png"]什乙。也可以用 Target 方式制作 bundle,比如 iOS Library With Resourceshttp://www.galloway.me.uk/tutorials/ios-library-with-resources/.

14已球、如果 SDK 有用到 Category臣镣,注意項目設(shè)置 Other Linker Flags 添加 -ObjC。(后邊介紹了-ObjC的作用)

補充

編譯過程:

從C代碼到可執(zhí)行文件經(jīng)歷的步驟是:源代碼 > 預(yù)處理器 > 編譯器 > 匯編器 > 機器碼 > 鏈接器 > 可執(zhí)行文件

在最后一步需要把.o文件和C語言運行庫鏈接起來智亮,這時候需要用到ld命令忆某。源文件經(jīng)過一系列處理以后,會生成對應(yīng)的.obj文件阔蛉,然后一個項目必然會有許多.obj文件弃舒,并且這些文件之間會有各種各樣的聯(lián)系,例如函數(shù)調(diào)用馍忽。鏈接器做的事就是把這些目標文件和所用的一些庫鏈接在一起形成一個完整的可執(zhí)行文件棒坏。Other linker flags設(shè)置的值實際上就是ld命令執(zhí)行時后面所加的參數(shù)

下面逐個介紹3個常用參數(shù):

-ObjC:加了這個參數(shù)后,鏈接器就會把靜態(tài)庫中所有的Objective-C類和分類都加載到最后的可執(zhí)行文件中

-all_load:會讓鏈接器把所有找到的目標文件都加載到可執(zhí)行文件中遭笋,但是千萬不要隨便使用這個參數(shù)坝冕!假如你使用了不止一個靜態(tài)庫文件,然后又使用了這個參數(shù)瓦呼,那么你很有可能會遇到ld: duplicate symbol錯誤喂窟,因為不同的庫文件里面可能會有相同的目標文件,所以建議在遇到-ObjC失效的情況下使用-force_load參數(shù)央串。

-force_load:所做的事情跟-all_load其實是一樣的磨澡,但是-force_load需要指定要進行全部加載的庫文件的路徑,這樣的話质和,你就只是完全加載了一個庫文件稳摄,不影響其余庫文件的按需加載


后期會試著把貝塞爾畫餅的demo封裝成framework,另外可能會增加Bundle文件的生成方法饲宿。

參考自1厦酬、iOS-制作Framework(最新)

? ? ? ? ? 2、iOS--創(chuàng)建你自己的Framework


最后瘫想,哪里不對的地方可以給我留言仗阅,我會及時改進的,謝謝大家国夜。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末减噪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌筹裕,老刑警劉巖醋闭,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異朝卒,居然都是意外死亡目尖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門扎运,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人饮戳,你說我怎么就攤上這事豪治。” “怎么了扯罐?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵负拟,是天一觀的道長。 經(jīng)常有香客問我歹河,道長掩浙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任秸歧,我火速辦了婚禮厨姚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘键菱。我一直安慰自己谬墙,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布经备。 她就那樣靜靜地躺著拭抬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪侵蒙。 梳的紋絲不亂的頭發(fā)上造虎,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音纷闺,去河邊找鬼算凿。 笑死,一個胖子當(dāng)著我的面吹牛急但,可吹牛的內(nèi)容都是我干的澎媒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼波桩,長吁一口氣:“原來是場噩夢啊……” “哼戒努!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤储玫,失蹤者是張志新(化名)和其女友劉穎侍筛,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撒穷,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡匣椰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了端礼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片禽笑。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蛤奥,靈堂內(nèi)的尸體忽然破棺而出佳镜,到底是詐尸還是另有隱情,我是刑警寧澤凡桥,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布蟀伸,位于F島的核電站,受9級特大地震影響缅刽,放射性物質(zhì)發(fā)生泄漏啊掏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一衰猛、第九天 我趴在偏房一處隱蔽的房頂上張望迟蜜。 院中可真熱鬧,春花似錦啡省、人聲如沸小泉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽微姊。三九已至,卻和暖如春分预,著一層夾襖步出監(jiān)牢的瞬間兢交,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工笼痹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留配喳,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓凳干,卻偏偏與公主長得像晴裹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子救赐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容