import UIKit extension RDReaderView: UIPageViewControllerDataSource, UIPageViewControllerDelegate { private func makeSinglePageChildVC(for pageNum: Int) -> RDReaderPageChildViewController { if pageNum == RDReaderView.blankPageNum || pageNum == RDReaderView.blankEndPageNum { return RDReaderPageChildViewController(contentView: UIView(), pageNum: pageNum) } let contentView = pageViewForDisplay(pageNum: pageNum) return RDReaderPageChildViewController(contentView: contentView, pageNum: pageNum) } private func nextPageNum(after pageNum: Int, isDualPage: Bool) -> Int? { let totalPages = numberOfPages() if pageNum == RDReaderView.blankEndPageNum { return nil } if isDualPage, let coverIndex = coverPageIndex { if pageNum == coverIndex { return RDReaderView.blankPageNum } if pageNum == RDReaderView.blankPageNum { let firstContent = coverIndex + 1 return firstContent < totalPages ? firstContent : nil } } let next = pageNum + 1 if next < totalPages { return next } if isDualPage { if let coverIndex = coverPageIndex { let adjustedIndex = pageNum - (coverIndex + 1) if adjustedIndex >= 0 && adjustedIndex % 2 == 0 { return RDReaderView.blankEndPageNum } } else { if pageNum % 2 == 0 { return RDReaderView.blankEndPageNum } } } return nil } private func prevPageNum(before pageNum: Int, isDualPage: Bool) -> Int? { if pageNum == RDReaderView.blankEndPageNum { let totalPages = numberOfPages() return totalPages > 0 ? totalPages - 1 : nil } if isDualPage, let coverIndex = coverPageIndex { if pageNum == RDReaderView.blankPageNum { return coverIndex } if pageNum == coverIndex + 1 { return RDReaderView.blankPageNum } } let prev = pageNum - 1 return prev >= 0 ? prev : nil } public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { guard let vc = viewController as? RDReaderPageChildViewController else { return nil } let isDualPage = landscapeDualPageEnabled && isLandscape let isRTL = pageDirection == .rightToLeft let targetNum = isRTL ? nextPageNum(after: vc.pageNum, isDualPage: isDualPage) : prevPageNum(before: vc.pageNum, isDualPage: isDualPage) guard let num = targetNum else { return nil } let targetVC = makeSinglePageChildVC(for: num) willPreviousTransitionToViewController = targetVC return targetVC } public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { guard let vc = viewController as? RDReaderPageChildViewController else { return nil } let isDualPage = landscapeDualPageEnabled && isLandscape let isRTL = pageDirection == .rightToLeft let targetNum = isRTL ? prevPageNum(before: vc.pageNum, isDualPage: isDualPage) : nextPageNum(after: vc.pageNum, isDualPage: isDualPage) guard let num = targetNum else { return nil } let targetVC = makeSinglePageChildVC(for: num) willNextTransitionToViewController = targetVC return targetVC } public func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { if completed, let firstVC = pageViewController.viewControllers?.first as? RDReaderPageChildViewController { let pn = firstVC.pageNum if pn != RDReaderView.blankPageNum && pn != RDReaderView.blankEndPageNum { currentPage = pn primePageCache(around: pn, preferredForward: predictedPageDirection) } } predictedPageDirection = nil finishPageCurlTransition() } public func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) { pagingController.isTransitioning = true willTransitionToViewController = pendingViewControllers.first if let target = pendingViewControllers.first as? RDReaderPageChildViewController, target.pageNum != RDReaderView.blankPageNum, target.pageNum != RDReaderView.blankEndPageNum { predictedPageDirection = target.pageNum >= currentPage primePageCache(around: target.pageNum, preferredForward: predictedPageDirection) } } }