問題描述
iOS開發(fā)中經(jīng)常要用到模擬器确封,甚至比真機(jī)被用得更頻繁礁阁。模擬器相對(duì)真機(jī)有下面幾種優(yōu)勢(shì):
* 模擬器一般不卡勾习,性能往往比在真機(jī)上跑更穩(wěn)定廊宪,因?yàn)殡娔X有更大的內(nèi)存矾瘾,更穩(wěn)定的網(wǎng)絡(luò)。
* 可以模擬系統(tǒng)箭启、設(shè)備壕翩、地理位置等。
* 調(diào)IM時(shí)傅寡,加一個(gè)模擬器放妈,就可以互發(fā)消息了。
* 導(dǎo)Sandbox數(shù)據(jù)方便荐操。
* 抓包比真機(jī)方便芜抒。
* 調(diào)試比真機(jī)方便,真機(jī)需要裝證書托启。
* ...
然而宅倒,有時(shí)候第三方SDK集成時(shí),第三方SDK可能不提供模擬器的x86架構(gòu)屯耸,那么在鏈接時(shí)拐迁,就會(huì)提示無法找到符號(hào)。
如項(xiàng)目中引入不支持模擬器的SDK疗绣,鏈接時(shí)线召,會(huì)報(bào)沒有找到x86_64架構(gòu)對(duì)應(yīng)的符號(hào):
如果用lipo -info 命令查看libMyLib.a這個(gè)庫,就會(huì)發(fā)現(xiàn)它只提供了 arm7和 arm64兩種架構(gòu)多矮,而沒有x86_64架構(gòu)灶搜。
# lipo -info libMyLib.a
Architectures in the fat file: libMyLib.a are: armv7 arm64
如果碰到這種庫,引入它之后工窍,項(xiàng)目就不再能在模擬器上運(yùn)行了割卖,因?yàn)樗溄佣疾粫?huì)過。而我們往往希望引入庫之前的其他功能仍能在模擬器上調(diào)試患雏。
解決思路
你可以要求SDK廠商提供模擬器的版本鹏溯,他們頂多改幾行腳本,多產(chǎn)生一個(gè)x86架構(gòu)淹仑,再把兩個(gè).a合并就行丙挽。但是如果碰上比較老沒有維護(hù)的SDK肺孵,或者廠商認(rèn)為SDK不需要考慮模擬器上運(yùn)行的場(chǎng)景,那就比較麻煩了颜阐。
你可以把所有用到SDK的代碼通過TARGET_OS_SIMULATOR宏來判斷平窘。但是這樣可能工作量比較大,而且容易出問題凳怨。
這里另外給出一種思路瑰艘,我們可以根據(jù)庫中的頭文件,自己空實(shí)現(xiàn)這些接口肤舞,最后編譯產(chǎn)生一個(gè)x86架構(gòu)的庫紫新,并把它加到工程里面,這樣工程鏈接時(shí)就不會(huì)出錯(cuò)了李剖。
空實(shí)現(xiàn)芒率,指的是函數(shù)里什么都不做,直接返回篙顺。如:
+ (instancetype)footerWithRefreshingTarget:(id)target refreshingAction:(SEL)action {
? ? return 0;
}
我們知道偶芍,objc里面,如果調(diào)用空對(duì)象的方法德玫,程序并不會(huì)有問題匪蟀,只是什么都不做。如下面代碼化焕,雖然footer為nil萄窜,仍不會(huì)崩潰。
MyRefreshFooter *footer = [MyRefreshFooter footerWithRefreshingTarget:nil refreshingAction:nil];
[footer resetNoMoreData];
所以在模擬器上除了SDK的功能不能用撒桨,其他模塊的功能并不會(huì)受影響查刻。
這種思路除了能解決編譯問題,還有種好處是凤类,不用改任何原來工程中的代碼穗泵,只是附加了一個(gè)x86的lib,不影響應(yīng)用在真機(jī)上的功能谜疤。
確定了這種思路后佃延,還可以把這種邏輯泛化應(yīng)用到任意的庫中,通過使用適當(dāng)?shù)墓ぞ咭目模梢宰詣?dòng)解析objc或cpp的頭文件履肃,產(chǎn)生相應(yīng)空實(shí)現(xiàn)的代碼,并編譯產(chǎn)生需要的x86架構(gòu)的庫坐桩。