iOS SDK 動態(tài)引入第三方SDK

引言

最近在做SDK拗军,我們的SDK中需要集成很多第三方庫殊轴,比如Twitter钦奋、Facebook等座云,我們SDK中需要用到這些第三方SDK中的登錄、分享等功能付材,這些第三方庫我們不會打包到我們自己的SDK中朦拖,而是接入方通過Pod或者其他方式導(dǎo)入到他們的工程。接我們SDK的人需求是不一樣的厌衔,有的只用到Facebook璧帝、有的只用到Twitter。如果有一個接入我們SDK的人只用到Facebook富寿,但是我們要求接入者不僅要導(dǎo)入Facebook的SDK睬隶,還要導(dǎo)入Twitter的SDK(因為SDK中集成了Twitter的東西,不導(dǎo)入會報錯)页徐,這樣是不是不太好苏潜,而且接入者可能會說,我們都沒有用到這個第三方变勇,為什么要導(dǎo)入他們的SDK恤左。

那么問題來了,我們要怎么樣才能做到我們SDK中既集成所有的第三方SDK搀绣,又能滿足接入者用到哪個第三方才導(dǎo)入對應(yīng)的第三方SDK飞袋?

解決方案

經(jīng)過一段時間的琢磨、想出了幾個方案:
方案一:在SDK內(nèi)部判斷是否導(dǎo)入了某個第三方庫豌熄,然后通過預(yù)編譯的方式授嘀,是否要編譯某段代碼(這個方案行不通)
方案二:SDK內(nèi)部通過runtime的方式調(diào)用第三方SDK的東西,通過動態(tài)的方式使用類锣险,方法及屬性(這個方法可以)
方案三:SDK 分成兩個部分蹄皱,一個部分是Framework部分览闰,一個部分是源碼部分,結(jié)合方案一和方案二(最終的方案)

下面詳細(xì)的說說這三種方案巷折,包括這三種方案使用時遇到的困難以及優(yōu)缺點

注意:本文中的代碼只是為了簡單的測試压鉴,在正常開發(fā)的時候,最好進(jìn)行一些相應(yīng)的判斷油吭,以免引起不必要的麻煩

方案一

直接上代碼,這是.m文件所有示例代碼

#import "Test.h"

// 判斷是否存在TwitterKit/TWTRKit.h署拟,如果存在說明導(dǎo)入了Twitter的SDK
#define TwitterSDKModule __has_include(<TwitterKit/TWTRKit.h>)

// 在導(dǎo)入了Twitter的SDK情況下婉宰,才引入
#if TwitterSDKModule
@import TwitterKit;
#endif

// 遵循Twitter的某個協(xié)議,以及使用Twitter的某個類的對象最為屬性
#if TwitterSDKModule
@interface Test()<這兒是Twitter的某個協(xié)議>
@property (nonatomic, strong) TWTRTwitter *twitter;
@end
#endif

// 跟Twitter沒關(guān)系的屬性
@interface Test()
@property (nonatomic, copy) NSString *message;
@end

@implementation Test

#if TwitterSDKModule

/// 調(diào)用Twitter的方法
- (void)loginByTwitter {
    [[Twitter sharedInstance] logInWithCompletion:^(TWTRSession * _Nullable session, NSError * _Nullable error) {
        
    }];
}

#endif

@end

原本信心滿滿推穷,但是慘慘招打臉心包,為什么這種方式不行呢?原因就在于我們打包Framework時馒铃,我們SDK內(nèi)部的代碼就編譯好了蟹腾,是否存在<TwitterKit/TWTRKit.h>在打包Framework時就決定了,而不是取決于接入者的工程中是否包含<TwitterKit/TWTRKit.h>区宇。所以這種方式宣告失敗

方案二

使用runtime方式娃殖。我們可以通過runtime的方式,在不引入頭文件的情況下進(jìn)行某個類的調(diào)用
具體參考代碼如下:

    // 獲取Person類
    Class personClass = NSClassFromString(@"Person");
    // 獲取方法編號
    SEL shareSEL = NSSelectorFromString(@"shared");
    // 調(diào)用Person類的類方法
    [personClass performSelector:shareSEL withObject:nil];
    // 創(chuàng)建實例化對象
    id person = [[personClass alloc] init];
    // 獲取對象的屬性
    NSString *name = [person valueForKey:@"name"];
    // 給屬性賦值
    [person setValue:@"xiao hai" forKey:@"name"];
    // 獲取方法編號
    SEL runSEL = NSSelectorFromString(@"run");
    // 實例方法的調(diào)用
    [person performSelector:runSEL withObject:nil];

這里獲取類议谷、調(diào)用類方法炉爆、獲取屬性值、給屬性賦值柿隙、調(diào)用實例方法都有了叶洞,那么問題來了鲫凶,我們要怎么去遵循協(xié)議禀崖、實現(xiàn)協(xié)議的方法,常規(guī)寫法如下:

@interface Test ()<PersonDelegate>
@end

@implementation ViewController
- (void)eatWithPerson:(Person *)person {
    
}
@end

那么問題來了螟炫,如果不引入頭文件的情況下波附,PersonDelegate、Person都是未知的昼钻,代理方法里還有很多未知的類掸屡,我們應(yīng)該如何解決,首先“@interface Test ()<PersonDelegate>”中然评, PersonDelegate代理完全不用寫,之所以要寫,我個人理解是為了寫代碼方便亮钦,減少寫代碼帶來的錯誤
遵循代理解決了,那么代理方法的實現(xiàn)怎么解決抖锥,Person是未知的,直接寫上去肯定會報錯碎罚,我們只需要將Person用id代替就行了磅废,之所以可以這么寫,是因為這兩種寫法荆烈,方法名是一樣的拯勉,都是“eatWithPerson:”,這樣就解決了代理相關(guān)問題憔购,簡直perfect宫峦,實例代碼如下:

@interface Test ()
@end

@implementation Test
- (void)eatWithPerson:(id)person {
    
}
@end

本以為問題都解決了,但是又遇到問題了玫鸟,performSelector方法不支持多參數(shù)斗遏,于是苦苦尋找解決方法,終于在GitHub上找到了解決辦法鞋邑,MXRuntimeUtils幫我解決了這個問題诵次,非常感謝MXRuntimeUtils的作者。本應(yīng)該再次高興時枚碗,問題又又又出現(xiàn)了逾一,MXRuntimeUtils不支持block類型的參數(shù),于是我對MXRuntimeUtils做了改進(jìn)肮雨,增加了對block類型參數(shù)的支持遵堵,如果有需要的小伙伴可以聯(lián)系我
這種方式終于結(jié)束了,下面我說說這種方式很大的一個弊端怨规,每個使用第三方SDK的地方都要用這種方式來寫陌宿,我只能說太累,太麻煩了

方案三(最終方案)

把方案一和方案二結(jié)合波丰,并進(jìn)行改進(jìn)壳坪。我以SDK集成Facebook、Twitter為例子掰烟,下面我直接給出我們SDK在這塊的架構(gòu)示意圖


7E80D089C5A36B2FAA30D77A4FF12579.jpg

我針對這個圖解釋一下爽蝴,整個SDK分成兩個部分,F(xiàn)ramework部分和源文件部分纫骑,F(xiàn)ramework部分是我們常規(guī)把包達(dá)成Framework的形式蝎亚,源文件部分,主要是對第三方SDK的接口進(jìn)行二次封裝先馆,直接向SDK接入者暴露源代碼(完全不牽扯到我們SDK內(nèi)部業(yè)務(wù)发框,代碼暴露給接入者沒什么關(guān)系)。源文件中的Adapter(下面簡稱A)是對需要的第三方接口進(jìn)行整合煤墙,比如我們SDK需要集成Twitter和Facebook的登錄功能梅惯,A中就提供一個登錄接口(通過一個參數(shù)來判斷要調(diào)用Twitter的登錄還是Facebook的登錄)源文件中的對Twitter顾患、Facebook接口的二次封裝,通過方案一中使用的方法封裝个唧。Framework中的Adapter(下面簡稱B)是對A進(jìn)行翻譯江解,供Framework部分中其他地方直接調(diào)用。B是framework內(nèi)部文件徙歼,A是Framework外部文件犁河,B如何調(diào)用A呢,可以通過方案二中的runtime形式調(diào)用魄梯。
分析:這種方案也用到了跟方案一中幾乎一樣的方案桨螺,為什么方案一達(dá)不到效果,而這種方案可以酿秸,原因在于在這個方案中灭翔,把方案一中用到的東西放到了源代碼中。這兩種方案辣苏,區(qū)別在于我們寫的有關(guān)預(yù)編譯的部分的編譯時機(jī)肝箱,方案一,預(yù)編譯部分的代碼在打包Framework的時候就編譯好了稀蟋,而這種方案煌张,預(yù)編譯部分的代碼在接入方編譯時才編譯,達(dá)到了我們想要的效果退客。

結(jié)束語

如果有什么寫的不對的地方骏融,歡迎指正,如果有什么不明白的地方也很歡迎一起探討
作者聯(lián)系方式:QQ 782304472 (要加的小伙伴請寫明在此文章中看到的萌狂,謝謝)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末档玻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子茫藏,更是在濱河造成了極大的恐慌误趴,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刷允,死亡現(xiàn)場離奇詭異冤留,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)树灶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來糯而,“玉大人天通,你說我怎么就攤上這事∠ㄍ眨” “怎么了像寒?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵烘豹,是天一觀的道長。 經(jīng)常有香客問我诺祸,道長携悯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任筷笨,我火速辦了婚禮憔鬼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘胃夏。我一直安慰自己轴或,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布仰禀。 她就那樣靜靜地躺著照雁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪答恶。 梳的紋絲不亂的頭發(fā)上饺蚊,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機(jī)與錄音悬嗓,去河邊找鬼卸勺。 笑死,一個胖子當(dāng)著我的面吹牛烫扼,可吹牛的內(nèi)容都是我干的曙求。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼映企,長吁一口氣:“原來是場噩夢啊……” “哼悟狱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起堰氓,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤挤渐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后双絮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浴麻,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年囤攀,在試婚紗的時候發(fā)現(xiàn)自己被綠了软免。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡焚挠,死狀恐怖膏萧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤榛泛,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布蝌蹂,位于F島的核電站,受9級特大地震影響曹锨,放射性物質(zhì)發(fā)生泄漏孤个。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一沛简、第九天 我趴在偏房一處隱蔽的房頂上張望齐鲤。 院中可真熱鬧,春花似錦覆享、人聲如沸佳遂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丑罪。三九已至,卻和暖如春凤壁,著一層夾襖步出監(jiān)牢的瞬間吩屹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工拧抖, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留煤搜,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓唧席,卻偏偏與公主長得像擦盾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子淌哟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

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

  • 一迹卢、說明 從2019年3月份接手游戲SDK任務(wù)以來,我們完善了 登錄模塊徒仓、支付模塊腐碱、事件 統(tǒng)計模塊、分享模塊 等功...
    hylccmh閱讀 1,925評論 1 1
  • 這幾天公司有一個新的需求掉弛,就是要將我們開發(fā)的某些東西都抽取出來症见,打個比方我們開發(fā)了A項目,可以以后B項目要包含A項...
    黃魚兒啦啦啦閱讀 6,139評論 2 16
  • 你一成不變的冷漠 讓我在八九年的八月 渡過一個冬天 在最最敏感的時候 你凄婉的作別 無論是不是玩笑 都重創(chuàng)我易受傷...
    夫瑋閱讀 324評論 6 13
  • 業(yè)務(wù)流程時序圖 仔細(xì)閱讀并看懂 (不是看過殃饿,是看明白+看完 ?) 微信官方文檔 微信開放平臺文檔谋作; 1.下載微信支...
    刀魚要到島上掉閱讀 4,185評論 0 4
  • ?“當(dāng)我開始數(shù)算所獲得的恩福,我的生命就立刻煥發(fā)光彩壁晒〈擅牵”? ??感恩樓里的一個鄰居业栅,每次看見我都會沖著我微笑并且打...
    Ivy亞琪閱讀 192評論 0 0