iOS中responseToSelector()方法是不是需要優(yōu)化

在日常開發(fā)中我經(jīng)常會調(diào)用responseToSelector這個方法,尤其是是在我們寫的協(xié)議的類中我們經(jīng)常會有這樣的判斷爬坑。最近重新看《編寫高質(zhì)量iOS于OS X代碼的52個有效方法》這本書的時候作者提供了不一樣的思路撑帖,作者認(rèn)為可以在對象初始化的時候去判斷慌植,然后用枚舉的方式進行判斷弓叛,來防止每次查找的過程璃弄,提高開發(fā)效率哥捕,我當(dāng)時思考的問題是牧抽,應(yīng)該是第一次調(diào)用方法之后就存儲在了類的方法緩存列表中,之后每次調(diào)用responseToSelector()方法都會優(yōu)先在緩存列表中查找么遥赚。當(dāng)時認(rèn)為每次查找的算法復(fù)雜度O(1)的扬舒,對于程序的優(yōu)化沒有必要,而且如果代理方法很多的情況下凫佛,對象初始化也會增加程序的負(fù)荷讲坎,因為這個時候會把所有的方法加入到緩存列表,這樣的方案本身意義不大愧薛。然后我就去看runtime的源碼驗證我的想法晨炕,現(xiàn)在我們一起來看一下我們是不是有必要做這一塊的優(yōu)化。

1.responseToSelector() vs 作者的方案

日常使用方案

日常protocol的使用方式

作者的方案用OC的方案寫出來是下邊的樣子

對比兩種方法我們很容易明白作者的意圖是在程序每次創(chuàng)建的時候就先去我們的代理類中去讀取當(dāng)前代理類有沒有實現(xiàn)當(dāng)前的代理方法毫炉,然后創(chuàng)建一個狀態(tài)枚舉動態(tài)的存儲類的返回結(jié)果瓮栗,每次判斷方法可否執(zhí)行前只要進行一次簡單的位運算即可。這時我發(fā)現(xiàn)即使responseToObject()方法即便是O(1)操作瞄勾,在時間級的優(yōu)化上作者的方案顯然也是更好的费奸。但是作者的方案同樣有一些需要注意的問題。

1)假如說你的程序在收到一些服務(wù)器的返回結(jié)果之后用runtime添加代理方法进陡,而這個時候我們已經(jīng)創(chuàng)建了代理愿阐,那么這個時候是無法執(zhí)行代理方法的。所以這時還要再有動態(tài)的改變枚舉狀態(tài)的新的接口趾疚,此時程序的復(fù)雜性就會上升缨历。這個時候我覺得還是使用responseToSelect()方法更好一些以蕴。而且很少有程序會遇到這樣的情況,所以這一點只有遇到這種情況的時候注意即可辛孵。

2)在我們的程序中舒裤,可能會有多個對象成為一個協(xié)議的代理,我們不可能每次在協(xié)議創(chuàng)建的時候觉吭,再去專門的寫一個類來記錄狀態(tài)那樣程序的耦合性無疑有上升了腾供,而且也沒有意義,所以這個時候鲜滩,我們每一個協(xié)議都要跟隨一個類來做綁定伴鳖,用于記錄代理對象是不是可以執(zhí)行某個協(xié)議方法,即便是協(xié)議的繼承徙硅,一樣要創(chuàng)建多個相應(yīng)的綁定類榜聂。這樣雖然稍有麻煩,但是我覺得這一部分還是合理的嗓蘑。

3)如果代理方法很多的情況下须肆,在初始化階段無疑就增加了對應(yīng)的綁定的類的負(fù)荷,因為需要在初始化的時候去方法列表中讀取所有的方法桩皿,在存儲到方法緩存列表中去還是需要一些耗時的豌汇,所以這時其實需要做時間上的衡量之后進行選擇的。如果協(xié)議多次調(diào)用泄隔,方法少拒贱,那么作者的方案更好。如果協(xié)議的每個方法調(diào)用次數(shù)不多佛嬉,且協(xié)議的方法還很多的情況下逻澳,我認(rèn)為responseToSelect()方法應(yīng)該更好一些。

4)想到上邊的3個問題之后暖呕,我就思考是不是有更好的處理方案呢斜做,將綁定的類的負(fù)荷拆分到每一次方法的調(diào)用階段,即便出現(xiàn)方法一的情況湾揽,也不需要在協(xié)議的綁定類中添加狀態(tài)改變的操作瓤逼。也不用再去考慮調(diào)用次數(shù)和方法數(shù)量之間的抉擇。我認(rèn)為我們可以將綁定關(guān)系的類進行一下修改即可钝腺。綁定類中的代碼修改如下抛姑。

優(yōu)化后的方案

經(jīng)過上邊的優(yōu)化后我們在第一次調(diào)用的時候會相應(yīng)responseToSelector()方法之后赞厕,如果響應(yīng)到了之后都是根據(jù)枚舉狀態(tài)去相應(yīng)艳狐。也沒有了綁定類一開始加載很多方法時會產(chǎn)生的高負(fù)荷,這樣的代碼看起來很好皿桑,但是對于那些占內(nèi)存很大的程序毫目,我覺得為了保護寶貴的內(nèi)存蔬啡,不去一次次創(chuàng)建這個雖然很小的綁定類。還是使用的系統(tǒng)的方案镀虐。因為我認(rèn)為系統(tǒng)的方案本身也是很好的(下文會有介紹),當(dāng)然這樣的方法對于程序的性能還是有優(yōu)化的刮便。與本文相關(guān)的demo下載地址

當(dāng)然看了我的思路之后恨旱,有更好的解決方案,煩請您給我留言搜贤,我會在本文中進行補充谆沃,大家一起成長~

說完了上邊的優(yōu)化,我們回頭再來看一下responseToSelector()到底在底層做了什么仪芒,它的運行效率到底是怎么樣的呢?

2)responseToSelector()的執(zhí)行效率怎么樣据沈?


這個時候我做的第一件事情就是去查看相關(guān)的源碼,起初先到objc-class.mm文件中去調(diào)用下邊的兩個方法饺蔑。 如果sel傳入空的或者類被釋放的話卓舵,其實直接就返回了NO.?

通過一系列的查詢之后,會發(fā)現(xiàn)程序被定位到了下邊的代碼處膀钠,這個方法在objc-runtime-new.mm文件中可以找到

查看了上邊的代碼的源代碼,我知道程序之后的調(diào)用方式其實就是先從緩存池中進行查找融击,沒有的情況下會從方法列表中取等一系列的操作雳窟。這篇文章可以看到lookupImporForward的實現(xiàn)的一些大體上的代碼,有比較詳細(xì)的注釋封救。這時我發(fā)現(xiàn)其實從緩存中讀取主要就是調(diào)用了 ?_cache_getImp(cls, sel) 這個方法,但是我從源碼中沒有找到這個方法誉结,后來在網(wǎng)上查到了美團技術(shù)團隊對于這一塊的解釋,才知道這一部分的實現(xiàn)使用匯編語言掉盅。但是讀取美團的原文加上我從國外網(wǎng)站上看到的文章,我才知道原來在方法列表的緩存列表中讀取到已執(zhí)行過的方法在算法的復(fù)雜度上并不是O(1)的趾痘。但是那一塊的執(zhí)行都是匯編實現(xiàn),所以執(zhí)行效率還是比較快的卵贱,所以系統(tǒng)對于這一塊的執(zhí)行速度還是很有保證的侣集,但是速度上肯定比不上一次位運算。

所以在具體的場景下肚吏,我們追求極致的用戶體驗的時候,這樣的方式真的值得我們思考和引用党觅。

如果文章中有任何問題斋泄,希望您不吝指出杯瞻,我一定會及時進行修復(fù)炫掐。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市旗唁,隨后出現(xiàn)的幾起案子痹束,更是在濱河造成了極大的恐慌,老刑警劉巖祷嘶,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件论巍,死亡現(xiàn)場離奇詭異烛谊,居然都是意外死亡嘉汰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門湃崩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來接箫,“玉大人,你說我怎么就攤上這事薄扁》侠郏” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵日缨,是天一觀的道長。 經(jīng)常有香客問我匣距,道長哎壳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任尸红,我火速辦了婚禮刹泄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘特石。我一直安慰自己,他們只是感情好风科,可當(dāng)我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布乞旦。 她就那樣靜靜地躺著,像睡著了一般兰粉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上愕秫,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機與錄音戴甩,去河邊找鬼。 笑死协饲,一個胖子當(dāng)著我的面吹牛缴川,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播把夸,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼恋日,長吁一口氣:“原來是場噩夢啊……” “哼吞获!你這毒婦竟也來了谚鄙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤烤黍,失蹤者是張志新(化名)和其女友劉穎傻盟,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體规哲,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡诽表,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了袄简。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泛啸。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出种柑,到底是詐尸還是另有隱情匹耕,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布良漱,位于F島的核電站欢际,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏损趋。R本人自食惡果不足惜椅寺,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望返帕。 院中可真熱鬧,春花似錦镊靴、人聲如沸链韭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至殖蚕,卻和暖如春沉迹,著一層夾襖步出監(jiān)牢的瞬間嫌褪,已是汗流浹背胚股。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留缨伊,地道東北人。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓枷恕,卻偏偏與公主長得像谭胚,于是被迫代替她去往敵國和親徐块。 傳聞我的和親對象是個殘疾皇子灾而,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,044評論 2 355

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理旁趟,服務(wù)發(fā)現(xiàn),斷路器锡搜,智...
    卡卡羅2017閱讀 134,661評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,167評論 25 707
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,149評論 30 470
  • 高德地圖 高德地圖的一個可能實現(xiàn)方案耕餐。 以JavaScript為例 開發(fā) > JavaScript API > 開...
    優(yōu)雅的豬閱讀 5,733評論 0 2
  • 今天有風(fēng)肠缔,可是太陽很好。 開車要專心桩砰,悲不能沉溺,喜不能得意亚隅。拐彎的時候,聽到了清脆的刮擦聲煮纵,第一時間判斷,不是太...
    微危道人閱讀 371評論 18 35