I’m trying to implement a book like interface in my swift app where the spine of the book is at the centre and the user is able to view two pages. For this, I’m using the UIPageViewController class and creating an array of ViewControllers to be displayed on the screen.
I’m able to initialise the first two pages properly. However when I flip the page to view page 3 and 4, it takes me directly to the last page. I’ve used a ViewContorllerRespresentable to embed this into my Swift UI to see it on the screen.
Here is the code I’m using.
import SwiftUI
import UIKit
import Combine
class CustomPageViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let index = viewControllersList.firstIndex(of: viewController), index >= 2 else {
return nil
}
print("currrent index is", index)
let previousIndex = index - 2
print("MOVING BEHIND")
print(previousIndex+1)
print(previousIndex)
setViewControllers([viewControllersList[previousIndex], viewControllersList[previousIndex + 1]], direction: .reverse, animated: true){finished in
if finished{
print("completed move behind operation")
}
}
return nil // The system manages the transition; no need to return a single view controller.
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let index = viewControllersList.firstIndex(of: viewController), index < viewControllersList.count - 2 else {
return nil
}
print("currrent index is", index)
let nextIndex = index + 2
print("MOVING AHEAD")
print(nextIndex-1)
print(nextIndex)
setViewControllers([viewControllersList[nextIndex-1], viewControllersList[nextIndex]], direction: .forward, animated: true){finished in
if finished{
print("completed move ahead operation")
}
}
return nil // The system manages the transition; no need to return a single view controller.
}
lazy var viewControllersList: [UIViewController] = []
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
self.delegate = self
let firstViewController = UIViewController()
firstViewController.view.backgroundColor = .red
let secondViewController = UIViewController()
secondViewController.view.backgroundColor = .green
let thirdViewController = UIViewController()
thirdViewController.view.backgroundColor = .blue
let fourthViewController = UIViewController()
thirdViewController.view.backgroundColor = .yellow
let fifthViewController = UIViewController()
thirdViewController.view.backgroundColor = .black
let sixthViewController = UIViewController()
thirdViewController.view.backgroundColor = .magenta
viewControllersList = [firstViewController, secondViewController, thirdViewController, fourthViewController, fifthViewController, sixthViewController]
setViewControllers([viewControllersList[0], viewControllersList[1]], direction: .forward, animated: true){finished in
if finished{
print("set initial VC")
}
}
}
func pageViewController(_ pageViewController: UIPageViewController, spineLocationFor interfaceOrientation: UIInterfaceOrientation) -> UIPageViewController.SpineLocation {
if interfaceOrientation.isLandscape{
// self.isDoubleSided = true
print("INSIDE THIS BLOCK OF CODE")
if let currentViewController = self.viewControllers?.first, let currentIndex = viewControllersList.firstIndex(of: currentViewController) {
let nextIndex = currentIndex + 1
let nextViewController = (nextIndex < viewControllersList.count) ? viewControllersList[nextIndex] : nil
if let nextVC = nextViewController {
setViewControllers([currentViewController, nextVC], direction: .forward, animated: true, completion: nil)
} else {
setViewControllers([currentViewController], direction: .forward, animated: true, completion: nil)
}
}
return .mid
}
else{
return .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()
}
}
}
I feel that I’m really close to making it happen but I’m missing a small detail. Appreciate your help on this