Rowan Freeman
Rowan Freeman

Reputation: 16388

Why isn't my PageViewController's DataSource working correctly?

I have created a simple storyboard with a PageView Controller.

I will flip between two other View Controllers.

My PageView Controller is a custom class TutorialPageViewController. I've also created a custom DataSource class.

In the DataSource class I expect the pageViewController methods to be called when I attempt to scroll. However this is not the case. I have break points at both methods and they are never called.

The first view controller, "Page the first" comes up correctly, but attempting to scroll around doesn't call the methods, so I can't use them yet (hence they return nil for now).

If I set the DataSource of my view controller to self and put the methods in there, they are called correctly. But I want to move the methods out to a separate class for better code management. So why doesn't it work?

I've tried

Storyboard overview

class TutorialPageViewController : UIPageViewController {
    override func viewDidLoad() {
        reset()
    }

    func reset() {
        let dataSource = TutorialPageDataSource(storyBoard: storyboard!)
        let content = dataSource.firstContentViewController

        self.dataSource = dataSource

        self.setViewControllers([content], direction: .forward, animated: true, completion: nil)
    }
}

class TutorialPageDataSource : NSObject, UIPageViewControllerDataSource {
    private var _storyboard: UIStoryboard

    var firstContentViewController: UIViewController
    var secondContentViewController: UIViewController

    init(storyBoard: UIStoryboard) {
        _storyboard = storyBoard
        firstContentViewController = _storyboard.instantiateViewController(withIdentifier: "FirstContentViewController")
        secondContentViewController = _storyboard.instantiateViewController(withIdentifier: "FirstContentViewController")
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        // break point here never reached
        return nil
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        // break point here never reached
        return nil
    }
}

Upvotes: 0

Views: 693

Answers (1)

rmaddy
rmaddy

Reputation: 318934

UIPageViewController dataSource (and delegate) are weak.

You create your TutorialPageDataSource instance in the reset method, assign it to the weak dataSource, and then the TutorialPageDataSource instance goes out of scope and gets deallocated because there is no strong reference to it any more. So now the page view controller's dataSource becomes nil.

You need to keep a strong reference to the TutorialPageDataSource instance. Use an instance variable to keep the reference.

Upvotes: 2

Related Questions