Austin Berenyi Austin Berenyi - 8 months ago 11518
Swift Question

How do I navigate forward and backward within UIPageViewController using buttons?

I'm creating an onboarding app for New Patients of a physical therapy clinic. The new patient will answer questions on each view controller within the

UIPageViewController
and tap a button to go to the next question.

I followed a tutorial and set up my
UIPageViewController
PageVC
along with 3 view controllers.
PageVC
currently changes pages by swiping, but I want to be able to navigate backward and forward through view controllers using two buttons that are subviews of
PageVC
itself. How do I accomplish this?

I like using
UIPageViewController
and want to understand it a bit more. If there is a more effective method besides using
UIPageViewController
to accomplish this same task I'm happy to consider it.

class PageVC: UIPageViewController, UIPageViewControllerDataSource {

private(set) lazy var orderedViewControllers: [UIViewController] = {
return [self.VCInstance(name: "BodyChart"),
self.VCInstance(name: "Symptoms"),
self.VCInstance(name: "HadSurgery")]
}()

private func VCInstance(name: String) -> UIViewController {
return UIStoryboard(name: "Main", bundle: nil) .
instantiateViewController(withIdentifier: name)
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else {
return nil
}

let previousIndex = viewControllerIndex - 1

guard previousIndex >= 0 else {
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
}

let nextIndex = viewControllerIndex + 1
let orderedViewControllersCount = orderedViewControllers.count

guard orderedViewControllersCount != nextIndex else {
return nil
}

guard orderedViewControllersCount > nextIndex else {
return nil
}

return orderedViewControllers[nextIndex]
}

override func viewDidLoad() {
super.viewDidLoad()

dataSource = self

if let firstViewController = orderedViewControllers.first {
setViewControllers([firstViewController], direction: .forward, animated: true, completion: nil)
}
}

}

Answer Source

I think what you're looking for is here. But this is another way.

UIPageViewController has an instance method transition. The snippet below will move from the first to the second page child view controller.

pageViewController.transition(from: pageViewController.viewControllers[0], to: pageViewController.viewControllers[1], duration: 0.3, options: UIViewAnimationOptions.curveEaseInOut, animations: nil, completion: nil)

PageVC currently changes pages by swiping, but I want to be able to navigate backward and forward through view controllers using two buttons

Add your buttons to page content, then disable horizontal scrolling on PageVC's scrollview or disable views' user interaction in a mannered fashion.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download