Search code examples
iosswift4segueuipageviewcontroller

PageViewController Disabled after pressing button with segue - Swift 4


I successfully implemented a PageViewController where I can swipe between five pages (ViewControllers). The problem is when I add a button that segues to one of the ViewControllers. It shows the page, like it is supposed to, but then I am stuck on that page. The PageViewController no longer works. I can't swipe between pages anymore.

import UIKit

class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {

    lazy var subViewControllers:[UIViewController] = {
        return [
            UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController1") as! ViewController1,
            UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController2") as! ViewController2,
            UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController3") as! ViewController3,
            UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController4") as! ViewController4,
            UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController5") as! ViewController5,
        ]
    }()

    override func viewDidLoad() {
    super.viewDidLoad()

        self.delegate = self
        self.dataSource = self

        setViewControllers([subViewControllers[0]], direction: .forward, animated: true, completion: nil)
    }

// MARK - UIPageViewControllerDataSource

    func presentationCount(for pageViewController: UIPageViewController) -> Int {
        return subViewControllers.count
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        let currentIndex:Int = subViewControllers.index(of: viewController) ?? 0
        if(currentIndex <= 0) {
            return nil
        }
        return subViewControllers[currentIndex-1]
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        let currentIndex:Int = subViewControllers.index(of: viewController) ?? 0
        if(currentIndex >= subViewControllers.count-1) {
            return nil
        }
        return subViewControllers[currentIndex+1]
   }
}

Solution

  • You can pass a reference of your PageViewController to your sub view controllers so that you can call method of your PageViewController from the sub view controllers. For example, create

    var pageViewController : PageViewController?
    

    in ViewController4 then assign it in the subViewControllers

    lazy var subViewControllers:[UIViewController] = {
        let viewController4 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController4") as! ViewController4
        viewController4.pageViewController = self
        return [
            UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController1") as! ViewController1,
            UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController2") as! ViewController2,
            UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController3") as! ViewController3,
            viewController4,
            UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController5") as! ViewController5,
        ]
    }()
    

    You can then call any method of the PageViewController from ViewController4. To make it simple, you can create a scrollToViewController3() method in PageViewController

    func scrollToViewController3()
    {
        setViewControllers([subViewControllers[2]], direction: .reverse, animated: true, completion: nil)
    }
    

    and call pageViewController?.scrollToViewController3() in ViewController4