import UIKit /// 翻页控制器:管理 UIPageViewController 的创建、切换、故障修复和翻页请求队列。 /// /// RDReaderView 持有此控制器,将 pageCurl 模式的容器管理职责下沉。 struct RDReaderPagingController { /// 当前 pageCurl 翻页请求模型 struct PageTransitionRequest: Equatable { let pageNum: Int let animated: Bool } /// 排队中的翻页请求(pageCurl 动画过程中收到新跳转时排队) var pendingTransitionRequest: PageTransitionRequest? /// 是否正在执行页面转场动画 var isTransitioning: Bool = false /// UI 是否已经构建完成(避免重复构建) var didBuildUI = false // MARK: - PageViewController 工厂 /// 创建带指定 spine 位置的 UIPageViewController static func createPageViewController(isDualPage: Bool) -> UIPageViewController { let options: [UIPageViewController.OptionsKey: Any]? if isDualPage { options = [.spineLocation: NSNumber(value: UIPageViewController.SpineLocation.mid.rawValue)] } else { options = nil } let pageVC = UIPageViewController(transitionStyle: .pageCurl, navigationOrientation: .horizontal, options: options) pageVC.isDoubleSided = isDualPage return pageVC } // MARK: - 翻页请求队列管理 /// pageCurl 动画过程中如果收到新的跳转请求,则排队等待当前动画结束。 mutating func shouldQueuePageTransition(_ request: PageTransitionRequest, currentDisplayType: RDReaderView.DisplayType) -> Bool { guard currentDisplayType == .pageCurl, isTransitioning else { return false } pendingTransitionRequest = request return true } /// 收尾 pageCurl 转场,返回排队中的后续请求(如果有的话)。 mutating func finishPageCurlTransition() -> PageTransitionRequest? { isTransitioning = false guard let pending = pendingTransitionRequest else { return nil } pendingTransitionRequest = nil return pending } /// 重置所有排队状态(用于故障修复)。 mutating func resetPendingState() { isTransitioning = false pendingTransitionRequest = nil } }