起因
我們公司上線了一個新版本之后,沒有對iPhone X有針對性的重新設計UI,照理只是做了簡單的視覺適配,比如navigationBar和一些自定義的bottomBar,對于其他的UI并沒有特別的操作。
于是,在一個清晨的時候,當我打開fabric的時候,發(fā)現我們的主頁出現了崩潰,而且居然是遞歸崩潰,仔細查看之后發(fā)現只在iPhone X上出現。
具體如下兩圖:


梳理邏輯
我們仔細梳理了一下首頁的UI邏輯:
1、首頁利用scrollViewDidScroll:這個方法了監(jiān)測首頁的滑動,當滑動范圍超過20pt的時候,通過滑動方向來控制隱藏和展示navigationBar。
2、進入首頁之后,或者切換首頁Tab的時候回觸發(fā)mj_header的beginRefreshing方法,自定義之后的mj_header的默認高度為52pt。
3、navigationBar的默認高度為44pt;
4、根據問題只出現在iPhone X上,可以猜測是當navigationBar執(zhí)行隱藏的時候,和其他設備的UI布局處理邏輯不同。
分析了一下崩潰日志:
1、scrollViewDidScroll:這個方法被觸發(fā)后,會根據互動距離以及方向類設置navigationBar隱藏或者展示。
2、navigationBar隱藏或者展示又反過來不斷觸發(fā)了scrollViewDidScroll:這個方法。
復現成功
當navigationBar隱藏情況下,切換Tab到一個新的頁面,出現mj_header刷新的UI之后出現崩潰。
分析原因
既然是遞歸,那么就要先找到loop的入口,這樣才好找出口。
1、分析崩潰日志之后,發(fā)現一個很有意思的地方,當navigationBar隱藏或者展示的時候,會觸發(fā)scrollViewDidScroll:這個方法,navigationBar的高度是44pt。
2、而當我們在navigationBar隱藏情況下,切換Tab到一個新的頁面的時候,觸發(fā)mj_header的beginRefreshing方法,繼而觸發(fā)scrollViewDidScroll:,mj_header*的默認高度為52pt,滑動距離的閾值是20pt。
所以我們簡單推斷出,這個遞歸問題的出現很有可能和這幾個數字有關系。
得出結論
最后判斷出結論是和我們設置的滑動距離的閾值有關系。
邏輯是這樣的:
1、當觸發(fā)mj_header的beginRefreshing方法得時候,scrollViewDidScroll:也會觸發(fā),產生的間隔是52pt,大于滑動的閾值20pt。于是會觸發(fā)navigationBar的展示方法。
2、當navigationBar的展示方法觸發(fā)之后,又會觸發(fā)scrollViewDidScroll:,產生的間隔是44pt,也大于滑動的閾值20pt。但是這個時候根據我們的判斷邏輯,會判斷滑動方向是向上的,所以會觸發(fā)當navigationBar的隱藏方法。
3、當navigationBar的隱藏方法觸發(fā)之后,又會觸發(fā)scrollViewDidScroll:,產生的間隔依然是44pt,依然也大于滑動的閾值20pt。這個時候會判斷為滑動方向是向下的,于是會觸發(fā)當navigationBar的展示方法。
4、于是周而復始,產生了遞歸。
解決方案
解決遞歸的方案只有一種思路,為loop尋找一個出口。
根據上面的復現規(guī)律得出一個結論,之所以產生了遞歸,是不斷的觸發(fā)scrollViewDidScroll:方法的時候,產生的間隔均大于閾值。
那么,當我們將閾值提高到比44pt大之后,每次navigationBar的展示和隱藏方法所觸發(fā)產生的距離將會小于這個預設的閾值,于是就不會進入向上向下滑動方向的判斷邏輯,繼而也就不會執(zhí)行展示和隱藏方法,這樣就算給loop找到了一個相當于優(yōu)雅的出口。
總結
在處理UI問題的時候,雖然適配機型過程中會出現各種各樣的問題,當問題出現的時候,我們需要一定要抓住觸發(fā)的原因,這樣才能更好的思考如何去繞過這個原因,以來解決問題。