You need to enable JavaScript to run this app. UINavigationController指定VC自定义转场时保留侧滑返回的方案咨询
优惠活动
大模型
产品
解决方案
定价
更多

UINavigationController指定VC自定义转场时保留侧滑返回的方案咨询

故障根因

当你实现了UINavigationControllerDelegate中的动画控制器代理方法后,系统会默认替换侧滑返回手势interactivePopGestureRecognizer的原有代理,你返回nil使用默认转场时,原有手势的判断逻辑没有正常触发,导致手势失效。

解决步骤

  • 第一步:初始化导航代理时,先保存系统原有侧滑手势的代理对象,再将手势代理设置为当前导航代理类。
  • 第二步:保持原有动画控制器代理的逻辑不变,仅目标VC场景返回自定义Animator,其余场景返回nil走系统默认转场。
  • 第三步:实现交互转场代理方法,自定义转场无交互需求时直接返回nil。
  • 第四步:实现UIGestureRecognizerDelegate协议,非自定义转场场景将手势判断逻辑转发给之前保存的系统原有代理,保证默认手势行为正常。

代码示例

首先定义导航代理的存储属性:

// 持有导航控制器引用
weak var navigationController: UINavigationController?
// 保存系统默认的侧滑手势代理
private var originalInteractivePopDelegate: UIGestureRecognizerDelegate?

初始化时配置手势:

// 设置导航代理时执行
func setup(for nav: UINavigationController) {
    navigationController = nav
    originalInteractivePopDelegate = nav.interactivePopGestureRecognizer?.delegate
    nav.interactivePopGestureRecognizer?.delegate = self
    nav.delegate = self
}

原有动画控制器代理逻辑保持不变:

func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    // 仅自定义目标VC的push和pop转场
    if operation == .push, toVC is TargetCustomViewController {
        return CustomPushAnimator()
    } else if operation == .pop, fromVC is TargetCustomViewController {
        return CustomPopAnimator()
    }
    // 其余场景走系统默认
    return nil
}

实现交互转场代理方法:

func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
    // 自定义转场需要支持交互侧滑时返回对应的交互控制器,无需求直接返回nil
    return nil
}

实现手势代理方法转发逻辑:

extension NavigationDelegate: UIGestureRecognizerDelegate {
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        guard gestureRecognizer == navigationController?.interactivePopGestureRecognizer,
              let nav = navigationController else {
            return true
        }
        // 根控制器禁止侧滑,和系统行为一致
        if nav.viewControllers.count <= 1 {
            return false
        }
        // 自定义转场场景按需控制手势是否生效,此处示例为自定义转场不支持侧滑,你可以根据需求调整
        if let topVC = nav.topViewController, topVC is TargetCustomViewController {
            return false
        }
        // 非自定义场景转发给系统原有代理
        return originalInteractivePopDelegate?.gestureRecognizerShouldBegin?(gestureRecognizer) ?? true
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        guard gestureRecognizer == navigationController?.interactivePopGestureRecognizer else {
            return false
        }
        return originalInteractivePopDelegate?.gestureRecognizer?(gestureRecognizer, shouldRecognizeSimultaneouslyWith: otherGestureRecognizer) ?? false
    }
}

补充说明

如果你的自定义转场需要支持交互侧滑,可以创建UIPercentDrivenInteractiveTransition实例,监听侧滑手势进度更新转场状态,手势结束时判断转场是完成还是取消即可。

内容的提问来源于stack exchange,提问作者Georg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 13:36:07