You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Pan手势控制UIPageViewController时无法加载前后页面内容

UIPageViewController手动控制滚动时前后页面不加载的问题

在UIPageViewController中嵌入了3个视图控制器,我从其中一个子视图控制器获取UIPageViewController的UIScrollView,通过UIPanGesture对其进行控制。当前始终处于中间的视图控制器,但存在一个问题:如果不使用UIPageViewController自带的滑动操作,前后页面的内容始终无法显示,只能看到UIPageViewController的背景。所有逻辑都在主线程执行,推测需要触发UIPageViewController提前准备前后页面的数据——观察到通过自带滑动操作时,会自动触发viewControllerBefore和viewControllerAfter方法。

相关代码

子控制器中控制UIPageViewController滚动的代码

@objc func panRecognized(gesture: UIPanGestureRecognizer) {
    DispatchQueue.main.async { [weak self] in
        guard let self else { return }
        
        switch overflowState {
        case .on(let lastRecordedGestureTranslation):
            if gesture.state == .ended || gesture.state == .possible {
                self.viewModel.chatScrollDetectedSwipeDirection = nil
                self.viewModel.objectToMove = nil
                self.viewModel.chatScrollViewPosition = self.checkTableViewPosition(chatTableView)
                self.viewModel.baseToControllerDelegate?.onOverflowEnded()
                overflowState = .off
                chatTableScrollView?.panGestureRecognizer.isEnabled = true
                self.viewModel.baseToControllerDelegate?.pageControllerSetContentOffsets(prog: 0)
                return
            }
            
            // 通知页面控制器开始滚动
            let fullTranslationY = gesture.translation(in: view).y
            let delta = fullTranslationY - lastRecordedGestureTranslation
            overflowState = .on(lastRecordedGestureTranslation: fullTranslationY)
            
            self.viewModel.baseToControllerDelegate?.onOverflow(delta: delta)
    }
}

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true // 允许同时触发scrollView的两个pan手势
}

控制UIPageViewController滚动的代码

func onOverflow(delta: CGFloat) {
    DispatchQueue.main.async { [weak self] in
        guard let self else { return }
        guard let scrollViewA = self.pageViewController?.view.subviews.first(where: { $0 is UIScrollView }) as? UIScrollView else { return }
        scrollViewA.contentOffset.y -= delta / 2
    }
}

已尝试的方案

  • 手动调用viewControllerBefore和viewControllerAfter方法,但没有效果。

疑问点

调用setViewController方法(无论是否开启动画)可以加载前后页面内容,但会出现视图两次滑动的 glitch,直到回到中间控制器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:02:47