日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

在项目中谨慎为系统类添加分类!!!!!

發布時間:2024/8/26 windows 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在项目中谨慎为系统类添加分类!!!!! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

結論:

1、堅決杜絕為系統類做方法交換(見到【class_replaceMethod】格殺勿論!)

2、為系統類添加分類時候,屬性和方法名必須加上【世上獨一無二】的前綴,避免沖突和混淆。


?

之所以讓我對上述行為恨之入骨是因為,今天為了一個bug,我花了將近半天時間苦苦追尋原因。

我只是使用了一個簡簡單單的UIImagePickerController的拍照的功能界面,奇葩的現象是,點擊快門按鈕時---可以看見界面中的按鈕發生了視覺上的響應,但是卻沒有功能上的響應(按道理,我這邊按下按鈕的時候,拍照就會完成輸出圖片數據)。

我的整個思考過程是這樣的:

點擊沒功能反應?難道有誰把這個類中的響應方法重寫了?

---尋找UIImagePickerController在整個項目中的出現,看有沒有對它做分類,或者是子類化。結果是沒有的!

那是不是關于UIImagePickerController這個類,隨著iOS的SDK的更新,我有些屬性或者方法需要適配下?

---我用iOS10.2和iOS11.2和最新的iOS11.4都看了一遍,都有這個問題。難道從iOS10開始就要有些跟之前不一樣的適配需要做?我翻看相關的適配博客,沒有發現!

難道是我對事件響應鏈做了一些調整?導致事件被阻斷?

---我回頭看了一眼UIImagePickerController對象創建后使用的是模態出來的,一個簡單的展示鏈,沒有問題!

難道多線程問題?

---NONONO!我核對了下代碼,整個過程都在主線程中,至于就算UIImagePickerController里面的處理上開了子線程,那也不歸我們管,它暴露出來的API肯定是在主線程的。

那就見鬼了~但是,不對啊,就這個簡單的UIImagePickerController,不至于啊!

---我應該是知道肯定是項目中的其他SDK的環境影響到了它,但是會是什么呢?為了更加確定我的這個想法,給自己繼續追尋原因的信心,我新建demo,這塊代碼原樣放入。臥槽,完美運行。

那行,我這樣的話,我要一查到底!

---能夠引起這個問題的全局原因,那么就是項目的配置數據有誤,那么就是分類的原因。

  項目的配置數據就是那些,最多就是在info文件中說明下使用相機的原因,方便獲取用戶的授權。因此我肯定,這塊沒有問題。

  分類的話,我已經確定了沒有UIImagePickerController的分類。那么肯定就是其他系統類的分類了。

  首先,添加分類的不可控性體現在:

(1)如果在分類中重寫類的方法,分類的重寫優先級是最高的?! ?/p>

(2)如果系統對UIImagePickerController添加了一些分類(包括不暴露在API中的),剛好又與項目中對其的分類方法名重復,會后入為主的。

(3)另外分類是會在編譯器就全部加上的,如果在分類中對類本身做的處理是會影響到類本身的。也就是說,如果對類中的方法做了方法轉移的處理,那就無形中影響了。

于是我趕緊搜索方法轉移的class_replaceMethod方法名有沒有在項目中出現。果然,項目中對UIButton的分類中重寫了+load類方法,在改方法中做了方法轉移!

正如前面分析的,重寫+load方法的優先級:分類中>子類中>類本身。

并且重寫的是+load這個方法,完全可以做到悄無聲息。

為了進一步驗證就是這個原因,我直接將這個分類的實現方法注釋掉,然后運行項目~【method_exchangeImplementations完美運作!!】


剛剛時候的是相當于反編譯的方式把問題的根源找到了,現在我需要的是使用順推的方法,把問題的出現原因梳理清楚。

通過查看UIButton的這個分類知道,它是將@selector(sendAction:to:forevent:)這個方法替換掉了。sendAction:to:forevent:方法中實際調用的是objc_setAssociatedObject,替換后的方法,在其中加了一個計時器,使得規定時間內,只能objc_setAssociatedObject調用一次。

這樣的做法,應該是為了防止button高頻按動而做的改動。

然而,UIImagePickerController功能界面中的快門按鈕,實際上是在拍照功能時,按住快門鍵不放,可以實現高頻連拍的功能(我試了下最多時999張),這樣的話,就很好解釋通了。雖然,按住快門鍵按鈕不放是一個“長按”手勢,但是其內部的實現肯定是高頻的調用@selector(sendAction:to:forevent:)這個方法。說到這里,我得說明下,雖然長按手勢和單點手勢表面上的確是不一樣的,但是其內部都調用了@selector(sendAction:to:forevent:)這個方法。因此,之前寫button這個分類的目的雖然是防止用戶高頻的單擊按鈕,但是現在用戶雖然不是高頻的單擊,而是長按,但是都調用的是@selector(sendAction:to:forevent:)這個方法。畢竟,當初為了防止用戶高頻單擊,是替換掉了@selector(sendAction:to:forevent:)這個方法。因此,謎底揭開了,整個離奇的故事真相大白~

轉載于:https://www.cnblogs.com/cchHers/p/9397085.html

總結

以上是生活随笔為你收集整理的在项目中谨慎为系统类添加分类!!!!!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。