簡體   English   中英

interactivePopGestureRecognizer 損壞根視圖控制器上的導航堆棧

[英]interactivePopGestureRecognizer corrupts navigation stack on root view controller

在我的UINavigationController中,我添加了自定義后退按鈕,其副作用是無法再從左向右滑動以彈出視圖控制器並向后導航。

所以我在我的自定義UINavigationController類中實現了interactivePopGestureRecognizer

class UINavigationControllerExtended: UINavigationController, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        if self.respondsToSelector(Selector("interactivePopGestureRecognizer")) {
            self.interactivePopGestureRecognizer?.delegate = self
        }
    }

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailByGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return gestureRecognizer.isKindOfClass(UIScreenEdgePanGestureRecognizer)
    }
}

這工作正常,除非我在我的根視圖控制器 (RVC) 中,它是一個UICollectionViewController ,即導航堆棧中最底部的視圖控制器。 當我做從左向右滑動的手勢時,似乎沒有發生任何事情,正如預期的那樣。 但是,當我隨后點擊 UICollectionViewCell 時,目標視圖控制器 (DVC) 不會被推到 RVC 上。 相反,我只在屏幕右側看到 DVC 的影子。

RVC 不再響應,但當我再次從左向右滑動時,DVC 交互地從右向左移動到屏幕中。 當我完成手勢時,DVC 完全移入屏幕,然后再次從左到右快速消失。 RVC 再次響應。

所以看起來 DVC 被推到導航堆棧上但沒有明顯地進入屏幕。

這種奇怪行為的起源有什么建議嗎?

為您的導航控制器實施UINavigationControllerDelegate並在那里啟用/禁用手勢識別器。

// Fix bug when pop gesture is enabled for the root controller
func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
    self.interactivePopGestureRecognizer?.enabled = self.viewControllers.count > 1
}

保持代碼獨立於推送的視圖控制器。

我當前的解決方案是在根視圖控制器中禁用interactivePopGestureRecognizer

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    self.navigationController?.interactivePopGestureRecognizer?.enabled = false
}

在第一個子視圖控制器中,我再次啟用它。 但這似乎更像是一種解決方法,因為我不明白為什么導航堆棧一開始就搞砸了的實際問題。

這是我的解決方案。 斯威夫特 4.2

實施UIGestureRecognizerDelegateUINavigationControllerDelegate協議。 在我的例子中,我在UITabBarController中執行了此操作,它也是我的根視圖控制器。

然后,在 viewDidLoad 上執行:

override func viewDidLoad() {
    super.viewDidLoad()

    self.navigationController?.interactivePopGestureRecognizer?.delegate = self
    self.navigationController?.delegate = self
}

然后,為UINavigationControllerDelegate添加委托方法,並通過計算導航控制器上的視圖數量來檢查它是否是根視圖,如果是則禁用它,如果不是則啟用它。

func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
    let enable = self.navigationController?.viewControllers.count ?? 0 > 1
    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = enable
}

最后,添加UIGestureRecognizerDelegate方法

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

這應該可以解決問題,而無需在項目的每個視圖中手動啟用/禁用手勢識別器。

func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
    self.interactivePopGestureRecognizer?.isEnabled = self.viewControllers.count > 1
}

更新了 Swift 5 的@rivera 解決方案

Guilherme Carvalho的解決方案對我有用,但我必須在viewWillAppear中分配委托方法,在viewDidLoad中對我的實現來說為時已晚。

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        navigationController?.interactivePopGestureRecognizer?.delegate = self
        navigationController?.delegate = self
    }

試試這個代碼

func navigationController(navigationController: UINavigationController, didShowViewController vc: UIViewController, animated: Bool) {
    self.interactivePopGestureRecognizer?.enabled = self.vc.count > 1
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM