Rowan Freeman Rowan Freeman - 1 year ago 79
Swift Question

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

. I've also created a custom DataSource class.

In the DataSource class I expect the
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
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

  • Setting my DataSource class to be a
    as well as a
    and setting the view controller's
    to be the DataSource

  • The PageView's transition style is Scroll

Storyboard overview

class TutorialPageViewController : UIPageViewController {
override func viewDidLoad() {

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

Answer Source

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.

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