Reputation: 1225
I have a View controller as describe below.
//
// PageViewController.swift
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
@Binding var currentPage: Int
init(controllers: [UIViewController], currentPage: Binding<Int>){
self.controllers = controllers
self._currentPage = currentPage
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .vertical
)
pageViewController.dataSource = context.coordinator
pageViewController.delegate = context.coordinator
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[controllers[currentPage]], direction: .forward, animated: true)
}
class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var parent: PageViewController
init(_ pageViewController: PageViewController) {
self.parent = pageViewController
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index == 0 {
return nil
}
return parent.controllers[index - 1]
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index + 1 == parent.controllers.count {
return nil
}
return parent.controllers[index + 1]
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed,
let visibleViewController = pageViewController.viewControllers?.first,
let index = parent.controllers.firstIndex(of: visibleViewController)
{
parent.currentPage = index
}
}
}
}
In my swiftUI file I have something similar to:
struct myCoolView : View {
@State var currentPage: Int = 0
var body: some View {
let subViews = [UIHostingController(rootView: mySubView(currentPage: $currentPage), ...]
return VStack{
PageViewController(controllers: subViews, currentPage: $currentPage)
}
In my Subviews I have buttons to go backward and forwards in the stack:
struct mySubView : View {
@Binding var currentPage: Int
var body: some View {
HStack {
Button(action: {self.currentPage -= 1}){
Text("Go Back")
}
Spacer()
Button(action: {self.currentPage += 1 }){
Text("Go Forward")
}
}
}
}
The go forward button behaves correctly, the coordinator calls updateUIViewController which activates the .forward
animation style. The issue is the back button ALSO displays the forward animation style when it should be calling the forward.
Ive toyed around with a few ways to solve this but none of them really work. What I really want is to create an extension that explicitly triggers either the go forward or go backward update flows. Any ideas how to accomplish that?
Thanks in advance
Upvotes: 2
Views: 1809
Reputation: 36
I had the exact same problem with the exact same example.
I solved it by comparing the index of the visible viewController to the "currentIndex" and adjusting the direction accordingly.
func updateUIViewController(_ pageViewController: UIPageViewController, context: UIViewControllerRepresentableContext<PageViewController>) {
var direction: UIPageViewController.NavigationDirection = .forward
if let visibleViewController = pageViewController.viewControllers?.first,
let index = controllers.firstIndex(of: visibleViewController),
index > currentPage {
direction = .reverse
}
pageViewController.setViewControllers([controllers[currentPage]], direction: direction, animated: true)
}
Upvotes: 2
Reputation: 36368
it seems to me you have one
@State var currentPage: Int = 0
that you use for a number of UIHostingController/mySubView and also in PageViewController. Try using different (an array of) var for each use.
Upvotes: 0