Search code examples
iosswiftuipageviewcontroller

UIPageViewController setViewControllers


I am trying to implement a PageViewController that switches to a different ViewController when a button is pressed. I can successfully load each "child" ViewController using the setViewControllers method during viewDidLoad().

However when I call the setViewControllers method outside viewDidLoad(), it does not change the current "child" ViewController.

Can you call the method setViewControllers at any point or just once during viewDidLoad()? Also is there a way to change a variable in the pageviewcontrollers dataSource extensions?

My project consists of a entry ViewController with a "Settings" button and a ContainerView. Inside the ContainerView I have the UIPageViewController.

Code for PageViewController:

import UIKit

class PageViewController: UIPageViewController {
var slides = [SlideItem]()
var currentIndex: Int!

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)!
    initSlides()
}

override func viewDidLoad() {
    super.viewDidLoad()

    if let viewController = viewSlideViewController(currentIndex ?? 0){
        let viewControllers = [viewController]

        setViewControllers(viewControllers, direction: .forward, animated: true, completion: nil)
    }

    dataSource = self

    // Do any additional setup after loading the view.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func viewSlideViewController(_ index: Int) -> SlideViewController? {

    guard let storyboard = storyboard,
    let page = storyboard.instantiateViewController(withIdentifier: "SlideViewController") as? SlideViewController else {
        return nil
    }

    page.slide = slides[index]
    page.slideIndex = index

    return page

}

func viewSettingsViewController(_ index: Int) -> SettingsViewController? {

    guard let storyboard = storyboard,
        let page = storyboard.instantiateViewController(withIdentifier: "SettingsViewController") as? SettingsViewController else {
            return nil
    }
    return page

}

func initSlides(){

    slides.append(SlideItem.init(filename: "Slide 1", comparison: false, highYield: false, videoURL: nil,
                                 groupOrganSystem: ["A"],
                                 groupMedicalSpecialty: ["B"]))
    slides.append(SlideItem.init(filename: "Slide 2", comparison: false, highYield: false, videoURL: nil,
                                 groupOrganSystem: ["A"],
                                 groupMedicalSpecialty: ["B"]))
}

func sidebarCommands(button: String, state: Bool){
    switch button {
        case "settings":
            self.setViewControllers([viewSettingsViewController(0)!], direction: .forward, animated: false, completion: nil)
            print("settings")
    default:
        return
    }
}

}

Extensions:

extension PageViewController : UIPageViewControllerDataSource {

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

    if let viewController = viewController as? SlideViewController,
        let index = viewController.slideIndex,
        index > 0 {
        return viewSlideViewController(index - 1)
    }
    return nil
}

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

    if let viewController = viewController as? SlideViewController,
        let index = viewController.slideIndex,
        (index + 1) < slides.count {
        return viewSlideViewController(index + 1)
    }
    return nil
}
}

enter image description here


Solution

  • Thank you for your help, I figured out what I was doing wrong. I didn't have the right reference for the active PageViewController in the ContainerView.

    So of course called the setViewControllers function on random PageViewController did not produce the correct results.

    I found this answer explains how to correctly get a reference from a ContainerView