UIPageViewController doesn't prepare initially neighbouring view controllers in Swift

117 Views Asked by At

I'm developing an iOS app using SwiftUI with UIKit's UIPageViewController with UIViewControllerRepresentable and I'm not good with UIKit. I have array of three view controllers which are UIHostingControllers to which I pass my SwiftUI view which is not very simple. When the app launches the second view controller is shown, but UIPageViewController does not prepare or pre-render the neighboring view controllers until I start swiping. At the moment when I start swiping the next view controller is getting updated (before swipe is finished). This causes a slight glitch on the first swipe that I'd like to avoid. After the first swipe, if I again swipe to that view controller the view update does not happen and further swipes are smooth without any glitches. So how can I prepare the neighbouring views when the app launches, maybe somehow manually render them, idk ...

struct ContentView: UIViewControllerRepresentable {

    @ObservedObject var viewModel: ViewModel

    var count: Int {
        viewModel.dayControllers.count
    }

    func makeUIViewController(context: Context) -> UIPageViewController {
        let pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal)
        pageViewController.dataSource = context.coordinator
        pageViewController.delegate = context.coordinator 

        pageViewController.setViewControllers([viewModel.dayControllers[(count-1)/2]], direction: .forward, animated: false, completion: nil)

        return pageViewController
    }

    func makeCoordinator() -> Coordinator {
    Coordinator(self)
}

class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
    // Implementation of ordinary coordinator methods
}

here is view model

class ViewModel: ObservableObject {
    @Published var dayControllers: [UIViewController]
//...
    init() {
        // Initialize dayControllers with view controllers
        self.dayControllers = dayVMs.map { dayVM in
            UIHostingController(rootView: SomeView(dayVM: dayVM)
                .equatable()
            )
        }
    }
}

I tried somehow manually prepare them in makeUIViewController(context: Context) -> UIPageViewController function like

pageViewController.setViewControllers([viewModel.dayControllers[(count-1)/2]], direction: .forward, animated: true, completion: {_ in
    
    viewModel.dayControllers[(count-1)/2-1].loadViewIfNeeded()

    viewModel.dayControllers[(count-1)/2+1].loadViewIfNeeded()
})

Or call before and after methods in the same function

//        let _ = context.coordinator.pageViewController(uiViewController, viewControllerBefore: viewModel.dayControllers[(count-1)/2-1])
//        let _ = context.coordinator.pageViewController(uiViewController, viewControllerAfter: viewModel.dayControllers[(count-1)/2+1])

But it didn't work.

Maybe there is some straightforward solution, would be happy if someone could help

0

There are 0 best solutions below