I have a UIPageviewcontroller which got two controllers inside. As you swipe to the next, I use the viewController argument to set the appropriate delegate. But I experience that if you swipe too fast, the function viewControllerAfter isn't updating the viewController correctly. The initially swipe should update the index of the viewcontroller from 0 to 1, but doesn't do so if you swipe too fast.
import UIKit
class WizardPageViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {
lazy var orderedViewControllers: [UIViewController] = {
return [self.newVc(viewController: "intro"),
self.newVc(viewController: "welcome")]
}()
var pageControl = UIPageControl()
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
self.delegate = self
configurePageControl()
// This sets up the first view that will show up on our page control
if let firstViewController = orderedViewControllers.first {
setViewControllers([firstViewController],
direction: .forward,
animated: true,
completion: nil)
}
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
let pageContentViewController = pageViewController.viewControllers![0]
self.pageControl.currentPage = orderedViewControllers.index(of: pageContentViewController)!
}
func newVc(viewController: String) -> UIViewController {
return UIStoryboard(name: "Wizard", bundle: nil).instantiateViewController(withIdentifier: viewController)
}
func configurePageControl() {
// The total number of pages that are available is based on how many available colors we have.
pageControl = UIPageControl(frame: CGRect(x: 0,y: UIScreen.main.bounds.maxY - 225,width: UIScreen.main.bounds.width,height: 50))
self.pageControl.numberOfPages = orderedViewControllers.count
self.pageControl.currentPage = 0
pageControl.isEnabled = false
//self.pageControl.tintColor = UIColor.black
self.pageControl.pageIndicatorTintColor = UIColor.gray
self.pageControl.currentPageIndicatorTintColor = UIColor(red:0.647, green:0.192, blue:0.216, alpha:1.00)
self.view.addSubview(pageControl)
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else {
return nil
}
print(orderedViewControllers.index(of: viewController))
let previousIndex = viewControllerIndex - 1
// User is on the first view controller and swiped left to loop to
// the last view controller.
guard previousIndex >= 0 else {
return nil
// Uncommment the line below, remove the line above if you don't want the page control to loop.
// return nil
}
guard orderedViewControllers.count > previousIndex else {
return nil
}
return orderedViewControllers[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else {
return nil
}
print(orderedViewControllers.index(of: viewController)) // Returns 0 is I swipe too fast, otherwise 1
if let vc = orderedViewControllers[viewControllerIndex] as? WelcomeViewController {
vc.delegate = self
}
let nextIndex = viewControllerIndex + 1
let orderedViewControllersCount = orderedViewControllers.count
// User is on the last view controller and swiped right to loop to
// the first view controller.
guard orderedViewControllersCount != nextIndex else {
return nil
// Uncommment the line below, remove the line above if you don't want the page control to loop.
// return nil
}
guard orderedViewControllersCount > nextIndex else {
return nil
}
return orderedViewControllers[nextIndex]
}
}
I've encountered exactly the same problem. It essentially boils down to
UIPageViewController
(_UIQueuingScrollView
to be exact) not updating its view hierarchy correctly.I noticed
UIPageViewController
is clever enough not to add/remove the content view if the page remains the same (even if it's in wrong place in the view hierarchy it somehow manages to cope with it so it looks good to the user). That's why I added aPageTrackingView
to observe the content view being added (or not) toUIPageViewController
view hierarchy. By tracking if the change happens I can calculate the current index by flipping it. So currently the workaround is good enough for 2 pages only.Try this. It's work for me.