Swift中使用UIPageViewController实现双页翻书界面问题求助
解决UIPageViewController双页翻页跳转异常问题
问题根源分析
你的代码存在三个核心问题导致翻页直接跳转到最后一页:
- 视图控制器初始化错误:第四到第六个VC的背景色被错误赋值给
thirdViewController,导致后续VC的引用和属性混乱,索引判断失效。 - DataSource方法滥用:
viewControllerBefore/viewControllerAfter中手动调用setViewControllers违背了UIPageViewController的工作机制,系统会自动根据返回的VC处理翻页,手动设置会打断正常流程。 - 索引逻辑错误:双页模式下的翻页索引计算逻辑有误,无法正确定位下一组双页的位置。
修正后的完整代码
import SwiftUI import UIKit class CustomPageViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource { // MARK: - DataSource Methods func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { guard let currentIndex = viewControllersList.firstIndex(of: viewController), currentIndex >= 2 else { return nil } // 返回上一组双页的第一个VC,系统会自动组合双页 return viewControllersList[currentIndex - 2] } func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { guard let currentIndex = viewControllersList.firstIndex(of: viewController), currentIndex < viewControllersList.count - 2 else { return nil } // 返回下一组双页的第一个VC,系统会自动组合双页 return viewControllersList[currentIndex + 2] } lazy var viewControllersList: [UIViewController] = [] override func viewDidLoad() { super.viewDidLoad() self.dataSource = self self.delegate = self self.isDoubleSided = true // 修正:每个VC独立设置背景色 let firstVC = UIViewController() firstVC.view.backgroundColor = .red let secondVC = UIViewController() secondVC.view.backgroundColor = .green let thirdVC = UIViewController() thirdVC.view.backgroundColor = .blue let fourthVC = UIViewController() fourthVC.view.backgroundColor = .yellow // 修正:给第四VC自己设置颜色 let fifthVC = UIViewController() fifthVC.view.backgroundColor = .black // 修正:给第五VC自己设置颜色 let sixthVC = UIViewController() sixthVC.view.backgroundColor = .magenta // 修正:给第六VC自己设置颜色 viewControllersList = [firstVC, secondVC, thirdVC, fourthVC, fifthVC, sixthVC] // 初始化显示第一组双页 setViewControllers([viewControllersList[0], viewControllersList[1]], direction: .forward, animated: true) { finished in print("初始双页设置完成") } } // MARK: - Spine Location Configuration func pageViewController(_ pageViewController: UIPageViewController, spineLocationFor interfaceOrientation: UIInterfaceOrientation) -> UIPageViewController.SpineLocation { if interfaceOrientation.isLandscape { // 确保当前显示的是双页 if let currentVC = viewControllers?.first, let index = viewControllersList.firstIndex(of: currentVC) { let nextIndex = index + 1 if nextIndex < viewControllersList.count { setViewControllers([currentVC, viewControllersList[nextIndex]], direction: .forward, animated: false) } } return .mid } else { // 竖屏显示单页 if let currentVC = viewControllers?.first { setViewControllers([currentVC], direction: .forward, animated: false) } return .min } } } // SwiftUI包装器 struct MyViewControllerRepresentable: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> CustomPageViewController { CustomPageViewController(transitionStyle: .pageCurl, navigationOrientation: .horizontal) } func updateUIViewController(_ uiViewController: CustomPageViewController, context: Context) {} } struct TestView : View { var body: some View{ VStack{ MyViewControllerRepresentable() .edgesIgnoringSafeArea(.all) // 让页面充满屏幕 } } }
关键修改说明
- 修复VC初始化错误:给每个VC独立设置背景色,避免属性覆盖导致的索引和显示混乱。
- 修正DataSource逻辑:移除
setViewControllers的手动调用,改为返回对应索引的VC,让UIPageViewController自动处理双页组合和翻页过渡。 - 完善翻页索引计算:双页模式下每次翻页移动2个索引,确保从
0-1到2-3再到4-5的正确跳转。 - 优化书脊位置逻辑:横屏时强制保持双页显示,竖屏时切换为单页,同时使用
animated: false避免不必要的动画干扰。
内容的提问来源于stack exchange,提问作者shangod
相关产品推荐
相关产品推荐

