嵌入两个UINavigationController作为子控制器后仅一个可响应的问题
我正在开发一个iOS项目,根控制器设为ContainerViewController,该控制器包含SideMenuViewController和MainViewController两个子控制器,通过手势实现侧边菜单的显示与隐藏。
在MainViewController中,又嵌套了MainTabController和以ConversationViewController为根控制器的conversationNavigationController,其中conversationNavigationController初始位于屏幕右侧外,可通过右滑手势调出。
当前问题:启动后MainTabController交互正常,但右滑显示conversationNavigationController后,它无法响应任何操作。
相关代码
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let scene = (scene as? UIWindowScene) else { return } window = UIWindow(windowScene: scene) window?.rootViewController = ContainerViewController() window?.makeKeyAndVisible() }
class ContainerViewController: UIViewController { var panGestureRecognizer: UIPanGestureRecognizer! private var menuWidth: CGFloat = UIScreen.main.bounds.width - 50 let menuController = SideMenuViewController() let mainController = MainViewController() override func viewDidLoad() { super.viewDidLoad() addChildVCs() panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))) view.addGestureRecognizer(panGestureRecognizer) } private func addChildVCs() { addChild(menuController) menuController.view.frame = CGRect(x: 0 - view.frame.size.width, y: 0, width: menuWidth, height: view.frame.size.height) view.addSubview(menuController.view) menuController.delegate = self menuController.didMove(toParent: self) addChild(mainController) mainController.delegate = self view.addSubview(mainController.view) mainController.didMove(toParent: self) } }
class MainViewController: UIViewController { let mainController = MainTabController() let conversationNavigationController = UINavigationController(rootViewController: ConversationViewController()) override func viewDidLoad() { super.viewDidLoad() addChildVCs() } private func addChildVCs() { addChild(mainController) mainController.menuDelegate = self view.addSubview(mainController.view) mainController.didMove(toParent: self) addChild(conversationNavigationController) conversationNavigationController.view.frame = CGRect(x: view.frame.size.width, y: 0, width: view.frame.size.width, height: view.frame.size.height) view.addSubview(conversationNavigationController.view) conversationNavigationController.didMove(toParent: self) } }
问题原因及解决方案
可能原因1:手势拦截触摸事件
ContainerViewController的panGestureRecognizer添加在根视图上,默认会拦截触摸事件(cancelsTouchesInView为true),导致下层的conversationNavigationController无法接收触摸信号。
解决方案:
在创建手势时设置cancelsTouchesInView = false,让手势识别的同时不阻断事件传递:
panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))) panGestureRecognizer.cancelsTouchesInView = false // 添加这一行 view.addGestureRecognizer(panGestureRecognizer)
可能原因2:视图层级或交互属性异常
- 检查conversationNavigationController及其子视图的
userInteractionEnabled是否被意外设置为false(默认是true,若代码中有修改需恢复)。 - 确认conversationNavigationController的view在滑入屏幕后,frame完全处于父视图(MainViewController的view)范围内,且父视图的
clipsToBounds为false(默认值,无需修改)。
可能原因3:手势冲突(若MainViewController也添加了右滑手势)
如果MainViewController自己实现了右滑调出conversation的手势,可能和ContainerViewController的侧滑手势冲突,导致事件被错误捕获。
解决方案:
在conversation显示时,暂时禁用ContainerViewController的pan手势,隐藏时重新启用:
// 在MainViewController的显示/隐藏conversation的方法中 func showConversation() { // 调出conversation的动画代码... (parent as? ContainerViewController)?.panGestureRecognizer.isEnabled = false } func hideConversation() { // 隐藏conversation的动画代码... (parent as? ContainerViewController)?.panGestureRecognizer.isEnabled = true }
内容的提问来源于stack exchange,提问作者user17031642

