import SwiftUI import UIKit class SomePageVC: UIViewController { let theLabel = UILabel() override func viewDidLoad() { super.viewDidLoad() theLabel.translatesAutoresizingMaskIntoConstraints = false view.addSubview(theLabel) NSLayoutConstraint.activate([ theLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), theLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor), ]) theLabel.font = .systemFont(ofSize: 60.0, weight: .light) } } class CustomPageViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource { func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { guard let index = viewControllersList.firstIndex(of: viewController), index > 0 else { return nil } if let vc = viewControllersList[index - 1] as? SomePageVC { print("viewControllerBefore:", vc.theLabel.text) } return viewControllersList[index - 1] } func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { guard let index = viewControllersList.firstIndex(of: viewController), index < viewControllersList.count - 1 else { return nil } if let vc = viewControllersList[index + 1] as? SomePageVC { print("viewControllerAfter:", vc.theLabel.text) } return viewControllersList[index + 1] } lazy var viewControllersList: [UIViewController] = [] override func viewDidLoad() { super.viewDidLoad() self.dataSource = self self.delegate = self let colors: [UIColor] = [ .red, .green, .systemBlue, .yellow, .cyan, .lightGray, ] for i in 0..<6 { let vc = SomePageVC() vc.view.backgroundColor = colors[i % colors.count] vc.theLabel.text = "Page \(i)" viewControllersList.append(vc) } // if we have an odd number of "pages" we need to add a blank page at the end if viewControllersList.count % 2 == 1 { let vc = SomePageVC() vc.view.backgroundColor = .systemBackground vc.theLabel.text = "Blank" viewControllersList.append(vc) } if self.spineLocation == .mid { setViewControllers([viewControllersList[0], viewControllersList[1]], direction: .forward, animated: true) } else { setViewControllers([viewControllersList[0]], direction: .forward, animated: true) } } func pageViewController(_ pageViewController: UIPageViewController, spineLocationFor interfaceOrientation: UIInterfaceOrientation) -> UIPageViewController.SpineLocation { // safely unwrap optionals guard let curVC = pageViewController.viewControllers?.first, let idx = viewControllersList.firstIndex(of: curVC) else { fatalError("This should never happen!") } if interfaceOrientation.isLandscape { pageViewController.isDoubleSided = true let newIDX = (idx % 2 == 1) ? idx - 1 : idx setViewControllers([viewControllersList[newIDX], viewControllersList[newIDX + 1]], direction: .forward, animated: true, completion: nil) } else { pageViewController.isDoubleSided = false setViewControllers([viewControllersList[idx]], direction: .forward, animated: true, completion: nil) } return interfaceOrientation.isLandscape ? .mid : .min } } // 2. PageViewControllerRepresentable struct MyViewControllerRepresentable: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> CustomPageViewController { let pageViewController = CustomPageViewController(transitionStyle: .pageCurl, navigationOrientation: .horizontal) return pageViewController } func updateUIViewController(_ uiViewController: CustomPageViewController, context: Context) { // Update the UIPageViewController if needed } } struct TestView : View { var body: some View{ VStack{ MyViewControllerRepresentable() } } } #Preview { TestView() }