記錄使用performSelector產(chǎn)生的bug和調(diào)試過(guò)程

說(shuō)說(shuō)NSObject的 performSelector 系列函數(shù)

記錄調(diào)試這個(gè)bug的過(guò)程

說(shuō)說(shuō)遇到的bug

?????說(shuō)之前先說(shuō)說(shuō)遇到的bug,公司項(xiàng)目,Target最低終于支持iOS8以上,web頁(yè)以前使用的是UIWebView,iOS8之后,蘋(píng)果推出了WKWebView,新寫(xiě)的功能需要使用到WKWebView,在之前使用UIWebView的時(shí)候,H5為了兼容安卓和iOS,會(huì)做平臺(tái)類(lèi)型判斷,這次團(tuán)隊(duì)決定使用iOS,安卓和H5通用的一套javaScript和原生的APP交互SDK,最終挑選了DSBridge,文檔上說(shuō)是一款三端易用的現(xiàn)代跨平臺(tái) Javascript bridge, 通過(guò)它,你可以在Javascript和原生之間同步或異步的調(diào)用彼此的函數(shù),

????? 聯(lián)調(diào)過(guò)后,一切完美,同步,異步方式都可以調(diào)用,但是最終打包給測(cè)試同學(xué)的時(shí)候,崩潰了,經(jīng)過(guò)一番檢查,發(fā)現(xiàn)在同步調(diào)用情況下崩潰,并且在DEBUG模式下沒(méi)有崩潰,在RElease模式下崩潰,javascript回調(diào)客戶(hù)端注冊(cè)的方法的時(shí)候直接 EXC_BAD_ACCESS 經(jīng)過(guò)一番檢查,在同步或者異步方式回調(diào)的時(shí)候使用了 performSelector這個(gè)方法,先看看DSBridge部分源代碼:

-(NSString *)call:(NSString*) method :(NSString*) argStr {
  ...只貼重要部分
  // 異步調(diào)用
  SuppressPerformSelectorLeakWarning(
                                            [JavascriptInterfaceObject performSelector:selasyn withObject:arg withObject:completionHandler];
                                            );
    // 同步調(diào)用
    id ret;
   SuppressPerformSelectorLeakWarning(
                                      ret=[JavascriptInterfaceObject performSelector:sel withObject:arg];
                                   );
}

?????DSBridge這樣設(shè)計(jì),會(huì)因?yàn)楫惒秸{(diào)用的時(shí)候客戶(hù)端通過(guò)completionHandler直接回調(diào)web端,而同步的時(shí)候得到一個(gè)返回值,在執(zhí)行js,通過(guò)js回調(diào)給web端,其中JavascriptInterfaceObject是客戶(hù)端注冊(cè)的調(diào)用對(duì)象,可以看到使用了performSelector,同事確定release模式下崩潰,我看到EXC_BAD_ACCESS 首先想到的是某個(gè)對(duì)象被釋放掉了,但是又給這個(gè)對(duì)象發(fā)了消息,但是日志都能正確,一點(diǎn)一點(diǎn)定位位置,直到無(wú)意中將同步調(diào)用方法的接收參數(shù)ret 去掉,才發(fā)現(xiàn)沒(méi)有崩潰了,確定本次崩潰和performSelector有關(guān)。

?????仔細(xì)想想performSelector函數(shù)到底返回什么,說(shuō)不清楚,NSObject.h中沒(méi)有注釋?zhuān)臋n中寫(xiě)的返回值是void,函數(shù)定義的返回的是一個(gè)id類(lèi)型。于是寫(xiě)一個(gè)Demo測(cè)試,在debug模式下,給有個(gè)對(duì)象通過(guò)performSelector發(fā)送2個(gè)消息,這2個(gè)方法分別是方法A和方法B,方法A有返回值,方法B返回值為void,得到結(jié)果方法A的返回值是調(diào)用函數(shù)的返回值,調(diào)用方法B 直接崩潰。終于確定問(wèn)題。

?????為什么會(huì)崩潰呢,和調(diào)用方法是否有返回值有關(guān),以前也知道performSelector編譯器不會(huì)對(duì)對(duì)象,方法,進(jìn)行檢驗(yàn),會(huì)有內(nèi)存泄露的可能產(chǎn)生,performSelector會(huì)把編譯時(shí)做的事情放到了運(yùn)行時(shí)期,點(diǎn)擊這里去看一些performSelector的詳細(xì)介紹,因?yàn)椴恢兰磳⒄{(diào)用的selector是否有返回值,只有到了運(yùn)行期才去檢測(cè),調(diào)用了返回值為Void的一些函數(shù),相當(dāng)于直接是 id obj = void,當(dāng)然是OC語(yǔ)法不允許的,直接崩潰是必然的。

?????為什么我們自己的項(xiàng)目在Debug模式下正常呢,于是在項(xiàng)目中寫(xiě)了局代碼測(cè)試,發(fā)現(xiàn)會(huì)返回一個(gè)nil,猜測(cè)可能在哪個(gè)地方在進(jìn)行了方法交換,查了代碼,沒(méi)有查到,可能是在某個(gè)SDK中,如圖:


WX20180413-011434@2x.png

總結(jié)

本次調(diào)試bug慢比較慢的原因:

  1. 對(duì)performSelector只知道怎么去用,細(xì)節(jié)部分沒(méi)想過(guò),比如函數(shù)的返回值,將編譯時(shí)期可以報(bào)出的錯(cuò)誤放到了運(yùn)行時(shí)期,等等
  2. DSBridge源碼看過(guò),但是看的不仔細(xì),花了好一會(huì)才了解整體調(diào)用過(guò)程。
  3. 查bug的時(shí)候會(huì)去猜測(cè),可能是哪個(gè)原因,然后通過(guò)注釋代碼來(lái)找問(wèn)題(知識(shí)掌握的不牢固)
  4. 在使用第三方庫(kù)的時(shí)候一定要讀懂核心部分源碼,在遇到問(wèn)題的時(shí)候才能夠快速定位問(wèn)題。

歸根結(jié)底都是對(duì)知識(shí)掌握的不牢固,踩的坑還不夠多。
所有的bug都有他們必現(xiàn)的原因,只是我沒(méi)有找到原因而已。

我以為的不一定是我以為的

????? 原本以為已經(jīng)解決了這個(gè)問(wèn)題,但是自己寫(xiě)Demo的時(shí)候是在模擬器上測(cè)試,公司項(xiàng)目是在真機(jī)上測(cè)試,都在真機(jī)上運(yùn)行都沒(méi)有崩潰,寫(xiě)的demo也返回了第一個(gè)固定參數(shù),公司項(xiàng)目傳入?yún)?shù){"action":"customservice"} 就直接崩潰 在真機(jī)上和在模擬器上有什么不同嗎?模擬器和真機(jī)都是iOS 11.3系統(tǒng),自己公司的項(xiàng)目為什么會(huì)發(fā)生崩潰呢?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,828評(píng)論 25 709
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,525評(píng)論 19 139
  • 在俄羅斯的列夫·托爾斯泰紀(jì)念館里陳列著一張普希金娜新婚后不久的肖像畫(huà),這張肖像畫(huà)托爾斯泰從未見(jiàn)到過(guò),但小說(shuō)中出現(xiàn)在...
    pengbaoer閱讀 4,075評(píng)論 0 4
  • Too many tips that how we make a difference in life are t...
    吳必森Brady閱讀 206評(píng)論 2 0
  • 前言 在自動(dòng)化測(cè)試實(shí)踐過(guò)程中,必不可少的就是進(jìn)行日志管理,方便調(diào)試和生產(chǎn)問(wèn)題追蹤,python提供了logg...
    苦葉子閱讀 928評(píng)論 0 0

友情鏈接更多精彩內(nèi)容