現(xiàn)象
最近在我們的 App 中遇到了一個奇葩的問題史翘,在某種場景下枉长,App 會處于假死的狀態(tài)。
現(xiàn)象:點擊屏幕上的任何位置都沒有反應(yīng)琼讽,按 Home 鍵后再打開 App 才能正常
在一個不經(jīng)意的操作中必峰,終于發(fā)現(xiàn)了復(fù)現(xiàn)規(guī)律,當(dāng)進(jìn)入到某個特定的頁面后钻蹬,再 pop 回到 UINavigationController 的第一級時吼蚁,此時如果在屏幕邊緣右滑,問題就出現(xiàn)了问欠。
在我們的 App 中肝匆,這個特定的頁面是一個包含有 WKWebView 的 ViewController,當(dāng)時我們模仿了微信在左上角自定義了返回按鈕和關(guān)閉按鈕顺献。由于自定義了 leftBarButtons旗国,所以屏幕邊緣右滑返回的功能就失效了。我當(dāng)時理所當(dāng)然地在這個頁面中添加了以下代碼
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.interactivePopGestureRecognizer?.delegate = self
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer is UIScreenEdgePanGestureRecognizer, !self.webView.canGoBack {
return true
}
return false
}
當(dāng)我以為優(yōu)雅地解決了右滑返回的問題時注整,卻發(fā)現(xiàn)引入了這么嚴(yán)重的一個問題能曾。。设捐。
解決方案借浊?
于是我 Google 了一下,發(fā)現(xiàn)不少人都給出同一個建議萝招,看下面代碼
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
let isRoot = viewController == navigationController.viewControllers.first
navigationController.interactivePopGestureRecognizer?.isEnabled = !isRoot
}
問題是能解決,但是徹底解決問題了嗎存捺?
這個方案是去接管 UINavigationController
的 delegate
槐沼,當(dāng)在 UINavigationController
的第一級時關(guān)閉屏幕邊緣右滑功能,反之則開啟捌治。
但大家是否有想過這樣的問題:
- 一般的 iOS App 都有幾個 Tab(我們的 App 就有三個 Tab)岗钩,這就意味著每一個 Tab 的
UINavigationController
都要去做這個處理,萬一哪天增加了一個 Tab 但沒有做這個處理肖油,那問題同樣會遇上兼吓。 - App 中也經(jīng)常會做 present 操作,而 present 出來的 ViewController 一般也會在 UINavigationController 里面森枪,同樣要處理视搏,否則還會遇上這個問題审孽。
這樣才是正解
想到上面兩個場景,不寒而栗浑娜,另謀其它解決方案佑力!
回想一下問題出現(xiàn)的過程,如果不進(jìn)入到那個特定的 ViewController筋遭,在屏幕邊緣右滑是沒有問題的打颤,而進(jìn)入到特定頁面再出來問題就出現(xiàn)了,為什么這么奇怪漓滔?
由于改的代碼量很少编饺,很容易就關(guān)注到下面這個地方
navigationController?.interactivePopGestureRecognizer?.delegate
我修改過 delegate
對象,導(dǎo)致問題出現(xiàn)响驴,那原來的 delegate
對象必然不是空的反肋,并且原來的 delegate
對象保證了即使在 UINavigationController
的第一級右滑也不會有假死的問題,所以完美的解決方案其實很簡單踏施,先持有原 delegate 對象石蔗,最后再修改回去
weak var originalGestureDelegate: UIGestureRecognizerDelegate?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.originalGestureDelegate = self.navigationController?.interactivePopGestureRecognizer?.delegate
self.navigationController?.interactivePopGestureRecognizer?.delegate = self
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.interactivePopGestureRecognizer?.delegate = self.originalGestureDelegate
}
好奇
很好奇,原來的 delegate
對象到底是什么畅形?
打個斷點即可看到是 UINavigationInteractiveTransitionBase
的對象养距,這里來找到了個很好玩的東西,可以看看這篇文章
要養(yǎng)成一個好習(xí)慣
要養(yǎng)成一個好習(xí)慣日熬,修改一個級的屬性時棍厌,一定要先持有這個屬性后,再賦值竖席,最終要修改回來
這樣說可能有點繞耘纱,大家平時在做一些界面的時候,某些界面要隱藏掉導(dǎo)航欄毕荐,此時可不能粗暴地在這個頁面中將導(dǎo)航欄隱藏掉束析,正確的做法應(yīng)該跟上面的解決方案一樣,在 viewWillAppear
先持有上一個界面的導(dǎo)航欄狀態(tài)憎亚,在 viewWillDisappear
修改回原來的狀態(tài)
好慷在家
廣告時間
歡迎大家來下載我們的 App 好慷在家员寇,提供專業(yè)的保潔保姆服務(wù),38節(jié)活動進(jìn)行中第美,買份家務(wù)包年蝶锋,寵愛自己一整年!
都看完了什往,不點個贊就走扳缕,這樣是耍流氓知道嗎?????