Reputation: 563
So I have a ParentView
, which has a NavigationLink
, leading to a UIViewControllerRepresentable
-conforming PageViewController
.
Now that ParentView
also has some subscription on some publisher. Whenever that one is fired, not only will the ParentView
redraw all its content (which it should), it will also re-initialize the (already presenting) PageViewController
.
That leads to stuttering/glitching, because the PageViewController
is already presenting and using the controllers that are continually being resetted.
Below is the ParentView
and PageViewController
(without the Coordinator stuff), both is pretty vanilla. The commented guard line is a hack I tried to prevent it from updating if displayed already. It helps but it's still stuttering on every swipe.
So the question is: How can we prevent the updating of a presented ViewController-wrapped-View when its presenting View is redrawn?
struct ParentView: View {
@Binding var something: Bool
var body: some View {
NavigationLink(destination: PageViewController(controllers: controllers)) {
Text("Push me")
}
}
}
final class PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
private var currentPage = 0
init(controllers: [UIViewController]) {
self.controllers = controllers
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
pageViewController.dataSource = context.coordinator
pageViewController.delegate = context.coordinator
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
// I tried this: guard pageViewController.viewControllers!.isEmpty else { return }
pageViewController.setViewControllers(
[controllers[currentPage]], direction: .forward, animated: true)
}
}
Upvotes: 2
Views: 752
Reputation: 128
If your controllers don't change after being displayed once, you can simply call:
pageViewController.setViewControllers([controllers[currentPage]], direction: .forward, animated: true)
from the makeUIViewController(context:)
function instead of the updateUIViewController(:)
function.
Upvotes: 1