0

I'm fairly new to Swift and so I'm having a pretty basic issue but I can't seem to find an answer to it. I have a ViewController with a container view. A Page Controller is embedded in the container view and I am able to scroll through the different pages but the issue I'm having is I want to change the pages based on a button I press in the ViewController.

This is my code for my PageController:

var pageIndex = 0

class FirstViewController: UIViewController {

    @IBOutlet weak var FirstButton: UIButton!
    @IBOutlet weak var SecondButton: UIButton!
    @IBOutlet weak var currentView: UIView!

    override func viewDidLoad() {
            super.viewDidLoad()
        }
    @IBAction func FirstButtonAction(_ sender: Any) {
        SecondButton.backgroundColor = UIColor.black
        SecondButton.setTitleColor(.white, for: .normal)

        FirstButton.backgroundColor = UIColor.white
        FirstButton.setTitleColor(.black, for: .normal)

         pageIndex = 0

    }

    @IBAction func SecondButtonAction(_ sender: Any) {

        FirstButton.backgroundColor = UIColor.black
        FirstButton.setTitleColor(.white, for: .normal)

        SecondButton.backgroundColor = UIColor.white
        SecondButton.setTitleColor(.black, for: .normal)

         pageIndex = 1

    }
}
class PageViewController: UIPageViewController, UIPageViewControllerDataSource {

    lazy var viewControllerList:[UIViewController] = {

        let sb = UIStoryboard(name: "Main", bundle: nil)

        let vc1 = sb.instantiateViewController(withIdentifier: "FirstVC")
        let vc2 = sb.instantiateViewController(withIdentifier: "SecondVC")

        return [vc1, vc2]

    }()


    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {

    guard let vcIndex = viewControllerList.firstIndex(of: viewController) else {return nil}

        pageIndex = vcIndex - 1

        guard pageIndex >= 0 else {return nil}
        guard viewControllerList.count > 0 else {return nil}

        return viewControllerList[pageIndex]

    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {

         guard let vcIndex = viewControllerList.firstIndex(of: viewController) else {return nil}

        pageIndex = vcIndex + 1

        guard viewControllerList.count != pageIndex else {return nil}
        guard viewControllerList.count > pageIndex else {return nil}

        return viewControllerList[pageIndex]
    }


    override func viewDidLoad() {
        super.viewDidLoad()

        self.dataSource = self



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

        }
    }

Most of this is just Google searching and YouTube videos so if my code looks choppy anywhere else, please tell me how to fix it. Any recommendations?

Images to show kind of the result I'm looking for (pretty simple I guess):

UPDATE: I tried adding this but this didn't work:

@IBAction func SecondButtonAction(_ sender: Any) {

guard let currentViewController = 
PageViewController().viewControllerList.first else { return }

guard let nextViewController = 
PageViewController().dataSource?.pageViewController(PageViewController(), viewControllerAfter: currentViewController) else { return } 

PageViewController().setViewControllers([nextViewController], direction: .forward, animated: false, completion: nil)
}

image 1

image 2

  • Look at this post, it should solve your problem https://stackoverflow.com/questions/7208871/is-it-possible-to-turn-page-programmatically-in-uipageviewcontroller – lacefarin Apr 28 '20 at 05:49
  • Hey @LukaCefarin thanks for the pointer! I tried adding that to it on my IBAction but I only end up crashing the app. Any pointer on what I need to fix? The code is in the update of the post. – Derek Gonzalez Apr 28 '20 at 16:21

1 Answers1

1

You can use setViewControllers:direction:animated:completion: to turn your pages on button click.

    @IBAction func btnNextTapped(_ sender: Any) {
           guard let currentViewController = pageView.viewControllers?.first else { return }
           guard let nextViewController = pageView.dataSource?.pageViewController(pageView, viewControllerAfter: currentViewController) else { return }
           pageView.setViewControllers([nextViewController], direction: .forward, animated: false, completion: nil)
    }
Dhara Patel
  • 396
  • 3
  • 9
  • Hey Dhara! I tried adding the code to the IBAction but it just ends up crashing the app when I run it. I have the code in the update on this point. Do you mind giving me any pointers on what I need to fix? – Derek Gonzalez Apr 28 '20 at 16:22
  • you need to change PageViewController() with let parentVC = self.parent as? PageViewController in your SecondButtonAction method – Dhara Patel Apr 29 '20 at 04:36
  • I still get this error: Could not cast value of type 'UITabBarController' to 'Project.PageViewController' when I add the code to my method. – Derek Gonzalez Apr 29 '20 at 06:35
  • Ok, it is because in your case PageViewController is not parent controller, you have embedded PageViewController inside container view of ViewController – Dhara Patel Apr 29 '20 at 06:44
  • Can you please try with delegate, when you tap on secondButton, call delegate method which is inside your PageViewController and add change pages code in that method – Dhara Patel Apr 29 '20 at 06:47
  • I’m at a loss on how to actually call delegates and protocols. I’ve watched a ton of Youtube videos today and been all over Stackoverflow. Do you have any resources you can send me to? Or any recommendations on how to write it? – Derek Gonzalez Apr 30 '20 at 04:02
  • Please folleo this https://medium.com/@astitv96/passing-data-between-view-controllers-using-delegate-and-protocol-ios-swift-4-beginners-e32828862d3f to understand delegate – Dhara Patel Apr 30 '20 at 05:52