iOS 14 -[UIInputResponderController prepareToMoveKeyboardForInputViewSet:animationStyle:] crash 解決

問(wèn)題

7 月 8 日 iOS 14 beta 2 放出后,我們注意到一個(gè) crash 激增了起來(lái)。

這個(gè) crash 頂部的堆棧為:

0        _objc_retain (in libobjc.A.dylib)
1        -[UIInputResponderController prepareToMoveKeyboardForInputViewSet:animationStyle:] (in UIKitCore)
2        -[UIInputResponderController setKeyWindowSceneInputViews:animationStyle:] (in UIKitCore)
3        -[UIInputResponderController setInputViews:animationStyle:] (in UIKitCore)
4        -[UIInputResponderController setInputViews:animated:] (in UIKitCore)
5        -[UIInputResponderController setInputViews:] (in UIKitCore)
......

并且我們注意到,這個(gè)問(wèn)題的觸發(fā),和業(yè)務(wù)形態(tài)沒(méi)有特別密切的聯(lián)系,多個(gè) app 都遇到了這個(gè)崩潰,且量級(jí)不低。

修復(fù)方案

先拋出一下我們最后確定的修復(fù)方案:

hook 私有方法 -[UIInputViewSet restorableResponder],直接返回 nil。

由于是系統(tǒng)庫(kù)自身的問(wèn)題,我們沒(méi)有源碼,很難保證這個(gè)修復(fù)沒(méi)有引入新的坑。但從目前的測(cè)試結(jié)果來(lái)看,至少崩潰不再?gòu)?fù)現(xiàn)了,并且看起來(lái)有關(guān)聯(lián)的鍵盤(pán)場(chǎng)景,也沒(méi)有嚴(yán)重問(wèn)題。

原因定位

造成 crash 的原因,是系統(tǒng)私有類 UIInputViewSet 中的 restorableResponder 屬性,既不是 weak 也不是 strong,類似于 unsafe_unretained。所以當(dāng)它被訪問(wèn)時(shí),很容易造成野指針。當(dāng)它被賦值給一個(gè) __strong id 類型的變量時(shí),則會(huì)在 _objc_retain 中崩潰。

我們可以打符號(hào)斷點(diǎn),從匯編中確認(rèn), iOS 14 beta 2 中,restorableResponder 屬性的 getter 和 setter 方法,只是存取了一個(gè)內(nèi)存值,沒(méi)有做任何 weak 或 strong 應(yīng)有的操作。



(從匯編指令看,沒(méi)有 storeWeak 或 storeStrong 操作)

可以 hook -[UIInputViewSet restorableResponder] 方法,驗(yàn)證一下它的返回值是不是經(jīng)常是個(gè)野指針。

定位過(guò)程

是怎么定位到 -[UIInputViewSet restorableResponder] 方法的呢?我的思路是這樣的:

1、猜測(cè)問(wèn)題來(lái)源于最頂棧 -[UIInputResponderController prepareToMoveKeyboardForInputViewSet:animationStyle:] (in UIKitCore) 的參數(shù)

2、hook -[UIInputResponderController prepareToMoveKeyboardForInputViewSet:animationStyle:] 方法,獲取傳入的參數(shù),發(fā)現(xiàn)有兩個(gè)參數(shù),第一個(gè)參數(shù)類型是 UIInputViewSet,這兩個(gè)參數(shù)本身不是野指針。

3、hook -[UIInputResponderController prepareToMoveKeyboardForInputViewSet:animationStyle:],嘗試將傳入的兩個(gè)參數(shù)改成 nil,發(fā)現(xiàn) crash 不復(fù)現(xiàn)了。這基本可以確認(rèn)問(wèn)題出在參數(shù)上。但參數(shù)本身不是野指針,所以推測(cè)問(wèn)題出現(xiàn)在參數(shù)某個(gè)方法的返回值上。

4、根據(jù)一份舊的 UIInputViewSet 頭文件,在 lldb 中依次對(duì)這個(gè) UIInputViewSet 對(duì)象發(fā)送消息。發(fā)現(xiàn)其中有個(gè)屬性 restorableResponder,在舊版本上標(biāo)記為 weak,但 getter 方法 return 出來(lái)的地址不是一個(gè)對(duì)象。嚴(yán)重懷疑這是一個(gè)野指針。

5、hook -[UIInputViewSet restorableResponder],返回 nil,crash 不復(fù)現(xiàn),確認(rèn)問(wèn)題出在 -[UIInputViewSet restorableResponder] 方法上

6、通過(guò)匯編確認(rèn) restorableResponder 在 iOS 14 beta 2 上既不是 strong 也不是 weak

相信很多團(tuán)隊(duì)都遇到了這個(gè) crash,先前在網(wǎng)絡(luò)上搜索未果,暫且拋出我的解決方案,歡迎與大家交流。
當(dāng)然最終還是等蘋(píng)果爸爸真正修復(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ù)。

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