-ObjC 引起duplicated symbols的問題

項(xiàng)目是用CocoaPod構(gòu)建的,CocoaPod在生成項(xiàng)目的時(shí)候會(huì)自動(dòng)在Other Link Flags配置項(xiàng)上打上-ObjC茁肠,而且季惩,即使強(qiáng)行去除-ObjC選項(xiàng)也無法解決,雖然編譯可通過掘剪,但是運(yùn)行的時(shí)候平委,友盟、MJRefresh等眾多庫均會(huì)報(bào)錯(cuò)無法運(yùn)行夺谁。

同時(shí)廉赔,公司的項(xiàng)目基于另一個(gè)分公司所提供的一個(gè)基礎(chǔ)服務(wù)framework,這個(gè)framework具體實(shí)現(xiàn)未知匾鸥,目前看來應(yīng)該是使用c++開發(fā)蜡塌,同時(shí)庫必須禁用掉-ObjC選項(xiàng),否則會(huì)報(bào) duplicated symbols錯(cuò)誤勿负,編譯都無法通過馏艾。

于是坑就這樣出來了。


-ObjC是干嘛的奴愉?

簡單來說琅摩,-ObjC鏈接指令是用來解決static library在運(yùn)行時(shí)調(diào)用category方法報(bào)selector not recognized錯(cuò)誤時(shí)使用的。也就是說锭硼,如果你在一個(gè)static library里面聲明了一個(gè)category房资,在運(yùn)行的時(shí)候調(diào)用這個(gè)方法就很有可能會(huì)出現(xiàn)這個(gè)錯(cuò)誤,而這個(gè)錯(cuò)誤本不應(yīng)該出現(xiàn)檀头,因?yàn)槟阋呀?jīng)定義了那個(gè)方法轰异。那么,為什么會(huì)出現(xiàn)這樣一個(gè)問題鳖擒?

為啥會(huì)出 method not recognized 錯(cuò)誤

簡單來說溉浙,這是因?yàn)閁NIX 的靜態(tài)庫(.a文件)與OC的動(dòng)態(tài)機(jī)制之間的不協(xié)調(diào)導(dǎo)致的。

我們先來看一般情況下蒋荚,UNIX靜態(tài)庫及C程序的一個(gè)鏈接過程戳稽。當(dāng)一個(gè)C語言程序編譯的時(shí)候,所有的源代碼會(huì)被編譯為對象文件期升,即.o文件(object file)惊奇。這些對象文件中包含了相應(yīng)的可執(zhí)行程序,以及相應(yīng)的靜態(tài)數(shù)據(jù)播赁。鏈接器最終需要將所有這些對象文件組合到一起從而產(chǎn)生一個(gè)最終的可執(zhí)行文件颂郎。

當(dāng)一個(gè)源文件引用了定義于其他文件中的一些東西的時(shí)候(比如引用其他文件的一個(gè)方法),一個(gè) undefined symbol就被寫入了它所產(chǎn)生的object 文件容为,然后等待最終被解釋掉乓序。在最終構(gòu)建可執(zhí)行文件的時(shí)候寺酪,鏈接器將從包含這些undefined symbols的object文件中拉取信息以解決掉之前被標(biāo)記的undefined symbols。

一個(gè)UNIX的靜態(tài)庫其實(shí)就是一系統(tǒng)object file的集合替劈,然而寄雀,一般情況下只會(huì)拉取那些,他需要的object file陨献。而這樣做的好處是可以減小最終可執(zhí)行文件的大小盒犹。

舉個(gè)例子

比如main.c使用一個(gè)函數(shù),名叫foo( )眨业,而這個(gè)函數(shù)定義于B.c里面急膀。在生成.o文件的時(shí)候,main.o就會(huì)有一個(gè)foo( ) 的undefined symbols標(biāo)記龄捡。在鏈接期間卓嫂,B.o文件便會(huì)被打入最終的可執(zhí)行文件中。但是墅茉,假如另外還有一個(gè)C.c命黔,里面定義了的函數(shù)并沒被使用到,那么最終就斤,這個(gè)C.o文件便不會(huì)出現(xiàn)在最終的可執(zhí)行文件中悍募。

Objective-C有什么不同?

然而眾所周之洋机,oc是具有一定動(dòng)態(tài)性的語言坠宴,只有在最終運(yùn)行的時(shí)候,對象方法的具體實(shí)現(xiàn)只有到被調(diào)用的時(shí)候才會(huì)被確定绷旗∠补模基于這個(gè)原因,Objective-C并沒有對方法級(jí)別定義符號(hào)衔肢,而是只對類級(jí)別定義符號(hào)庄岖。

舉個(gè)栗子。比如在main.c中包含以下代碼: [[FooClass alloc] initWithBar:nil]; 那么在鏈接的時(shí)候角骤,main.o在生成的時(shí)候就會(huì)包含一個(gè)未定義符號(hào)(Undefined Symbols) FooClass隅忿,但卻不會(huì)定義符號(hào) initWithBar。

所以為什么會(huì)產(chǎn)生這個(gè)坑邦尊?

坑爹的是背桐,Category只是一個(gè)方法的集合,而對一個(gè)Cateogry中的方法的調(diào)用蝉揍,并不會(huì)生成未定義符號(hào)链峭,這就意味著鏈接器并不知道要去加載這個(gè)Cateogry文件所生成的object 文件。于是又沾,在最后運(yùn)行的時(shí)候弊仪,運(yùn)行時(shí)系統(tǒng)便會(huì)無法找到相應(yīng)方法的定義熙卡,從而拋出unrecognized selector 錯(cuò)誤。

-ObjC干了啥励饵?

那為啥加上-ObjC就好了再膳? 原來,加上-ObjC選項(xiàng)的時(shí)候曲横,鏈接器便會(huì)加載靜態(tài)Library里面所有Objective-C實(shí)現(xiàn)的類和Cateogry。

還有啥選項(xiàng)不瓶?

除了-ObjC禾嫉,文檔上還有幾個(gè)其他的選項(xiàng),也值得我們關(guān)注一下蚊丐。

-all_load 全加載熙参,意思是加載所有靜態(tài)庫的成員。無論是c還是c++還oc麦备。

-force_load path_to_load 對某個(gè)指定靜態(tài)庫全加載孽椰。而-all_load則會(huì)對所有的庫進(jìn)行全加載。

這到這里凛篙,這個(gè)問題貌似已經(jīng)可以解決了黍匾。嗯,分公司的開發(fā)肯定在framework里面打包了幾個(gè)沒有用到的額外同名實(shí)現(xiàn)呛梆,而加上-ObjC锐涯,會(huì)將所有方法全加載上,于是duplicated symbols錯(cuò)誤便被拋出填物。那么纹腌,如果libPod,也就是pod庫生成的靜態(tài)庫前面加上-force_load滞磺,而不加上-ObjC升薯,問題不就順利解決了?

例如:

編譯用TARGET_BUILD_DIR击困,打包可用BUILT_PRODUCTS_DIR

-force_load $(TARGET_BUILD_DIR)/MJRefresh/libMJRefresh.a?

-force_load $(SRCROOT)/Pods/UMengUShare/UShareSDK/SocialLibraries/WeChat/WechatSDK/libWeChatSDK.a

framework類型的需要之后加 ?/庫名?

-force_load $(SRCROOT)/Pods/UMengUShare/UShareSDK/SocialLibraries/QQ/QQSDK/TencentOpenAPI.framework/TencentOpenAPI

引用:https://segmentfault.com/a/1190000005859469

參考:http://www.cocoachina.com/ios/20170110/18549.html涎劈,

http://blog.csdn.net/colorapp/article/details/39344639

http://blog.csdn.net/wlq861025/article/details/51888782

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沛励,一起剝皮案震驚了整個(gè)濱河市责语,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌目派,老刑警劉巖坤候,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異企蹭,居然都是意外死亡白筹,警方通過查閱死者的電腦和手機(jī)智末,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來徒河,“玉大人系馆,你說我怎么就攤上這事⊥缯眨” “怎么了由蘑?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長代兵。 經(jīng)常有香客問我尼酿,道長,這世上最難降的妖魔是什么植影? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任裳擎,我火速辦了婚禮,結(jié)果婚禮上思币,老公的妹妹穿的比我還像新娘鹿响。我一直安慰自己,他們只是感情好谷饿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布惶我。 她就那樣靜靜地躺著,像睡著了一般各墨。 火紅的嫁衣襯著肌膚如雪指孤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天贬堵,我揣著相機(jī)與錄音恃轩,去河邊找鬼。 笑死黎做,一個(gè)胖子當(dāng)著我的面吹牛叉跛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蒸殿,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼筷厘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了宏所?” 一聲冷哼從身側(cè)響起酥艳,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎爬骤,沒想到半個(gè)月后充石,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霞玄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年骤铃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拉岁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惰爬,死狀恐怖喊暖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情撕瞧,我是刑警寧澤陵叽,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站丛版,受9級(jí)特大地震影響咨跌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜硼婿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望禽车。 院中可真熱鬧寇漫,春花似錦、人聲如沸殉摔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逸月。三九已至栓撞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間碗硬,已是汗流浹背瓤湘。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恩尾,地道東北人弛说。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像翰意,于是被迫代替她去往敵國和親木人。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

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