'Programmatically set UIPageViewController Transition Style to Scroll

I am using Xcode 6 and implementing UIPageViewController for my app. I followed appcoda's tutorial, and everything works except the page indicators. This is because I cannot set the transition style of UIPageViewController to scroll.

Graphically, when I click on the PageViewController, the tab shows View Controller instead of Page View Controller like appcoda (See its image below)

enter image description here

This is what mine looks like:

enter image description here

And yes, my custom class is set to: UIPageViewController as it is in the tutorial. enter image description here

Programmatically, I try to set the transition style with:

    self.pageViewController.transitionStyle = UIPageViewControllerTransitionStyle.Scroll

but it fails to build, telling me that it Could not find member transition style. One last weird thing I would like to point out is that if I just write self.pageViewController.transitionStyle, it builds successfully, but it still uses the Page Curl Transition.

Could anyone help me? I am using Swift, Xcode 6, and developing on the iOS 8 SDK.



Solution 1:[1]

You're getting an error because transitionStyle is a readonly property. If you want to set the transition style of the page controller programmatically, it can only be done during initialization with the method:

init(transitionStyle style: UIPageViewControllerTransitionStyle, navigationOrientation navigationOrientation: UIPageViewControllerNavigationOrientation, options options: [NSObject : AnyObject]!) { ... }

More info in the documentation.

Solution 2:[2]

The issue is that when you create a UIPageViewController inside a Container, the container is first created with a UIViewController, and that s the controller you see your options for.

In order to fix it you have to delete UIViewController where you set your custom UIPageViewController. Then drag UIPageViewController from the controls picker and hook up the embed segue from the container to that controller, then you can set your custom pager controller as well as set transition to scroll.

Solution 3:[3]

Swift 3.0

required init?(coder aDecoder: NSCoder) {
    super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
}

Solution 4:[4]

in ios 8 swift3

override init(transitionStyle style: UIPageViewControllerTransitionStyle, navigationOrientation: UIPageViewControllerNavigationOrientation, options: [String : Any]? = nil) {
        super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: options)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

Solution 5:[5]

This is how I solved this problem in Swift 2.0

1. Created a class which is subclass of class UIPageViewController

    import UIKit
    
    class OPageViewController: UIPageViewController {
        
        override init(transitionStyle style: UIPageViewControllerTransitionStyle, navigationOrientation: UIPageViewControllerNavigationOrientation, options: [String : AnyObject]?) {

           // Here i changed the transition style: UIPageViewControllerTransitionStyle.Scroll           
            super.init(transitionStyle: UIPageViewControllerTransitionStyle.Scroll, navigationOrientation: UIPageViewControllerNavigationOrientation.Horizontal, options: options)
        }
    
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
    
    }

2.Than i just used it :D

pageController = OPageViewController()
pageController.dataSource = self
pageController.setViewControllers(NSArray(object: vc) as? [UIViewController], direction: .Forward, animated: true, completion: nil)
pageController.view.frame = CGRectMake(0, container.frame.origin.y, view.frame.size.width, container.frame.size.height);

Solution 6:[6]

I know this a little bit late, but I just had the same problem and realized that it was originated because I was using a simple UIViewController, even when my custom view controller class inherits from an UIPageViewController, aparently the graphic menu of xcode doesn't recognize it.

The solution was to delete in story board the view controller and drag a PageViewController to replace it. This will have the graphic menu with the scroll option.

Solution 7:[7]

Xcode 7.1 & Swift 2

All other solutions did not fully work for me at the latest Swift, especially since my class also inherits from UIPageViewControllerDataSource and UIPageViewControllerDelegate.

To set the PageViewController transition to .Scroll just add these 2 methods to your class:

override init(transitionStyle style: UIPageViewControllerTransitionStyle, navigationOrientation: UIPageViewControllerNavigationOrientation, options: [String : AnyObject]?) {
    super.init(transitionStyle: .Scroll, navigationOrientation: .Horizontal, options: options)
}

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

Solution 8:[8]

Swift 5 & 4: Just put this 2 functions before viewDidLoad() in your pageview VC

override init(transitionStyle style: UIPageViewController.TransitionStyle, navigationOrientation: UIPageViewController.NavigationOrientation, options: [UIPageViewController.OptionsKey : Any]? = nil) {
    super.init(transitionStyle: .pageCurl, navigationOrientation: .horizontal, options: nil)
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

Solution 9:[9]

Easiest way to do this programmatically in Swift 2.0 (without subclassing):

class PageViewController: UIPageViewController {

     override init(transitionStyle style: UIPageViewControllerTransitionStyle, navigationOrientation navigationOrientation: UIPageViewControllerNavigationOrientation, options options: [NSObject : AnyObject]!) {
          super.init(transitionStyle: .Scroll, navigationOrientation: .Horizontal, options: options) 
     }

}

Solution 10:[10]

This worked for me . Because if I override init for transitionStyle , it never gets called if you have set pageViewController in a container view in Storyboard.

required init?(coder aDecoder: NSCoder) {

        super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
    }

Solution 11:[11]

Swift 4 programmatically set the transition style of UIPageViewController

This is straight from 'UIPageViewController.h' line 61-97

Just put this before viewDidLoad() in your UIPageViewController() class

    override init(transitionStyle style: 
UIPageViewControllerTransitionStyle, navigationOrientation: UIPageViewControllerNavigationOrientation, options: [String : Any]? = nil) {
            super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
        }
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }

Solution 12:[12]

This is a known bug with UIPageViewController

You can read an explanation of the cause in this SO question and more comprehensively in this one.

I used the AppCoda Tutorial as well to get a handle on PageViewControllers. Another SO user actually wrote a gist that solved the problem for me in a way that I didn't have to change a line of code in my own project. Just drop AVC in to your project and call that instead of UIPageViewController in your code.

Paul de Lange's AlzheimerViewController.

Solution 13:[13]

swift 3 xcode 8 in

class ...: UIPageViewController {

override var transitionStyle: UIPageViewControllerTransitionStyle {
    return .scroll
}

override var navigationOrientation: UIPageViewControllerNavigationOrientation {
    return .horizontal
}

}

Solution 14:[14]

None of the solutions below worked for Swift 5. here is what worked for me, in my case i needed the view controller to be presented on top of the other view controller with low opacity background:

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nil, bundle: nil)

    self.setupView()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    self.setupView()
}

private func setupView() {
    self.modalTransitionStyle = .crossDissolve
    self.modalPresentationStyle = .overCurrentContext
    self.view.backgroundColor = UIColor.red.withAlphaComponent(0.3)
}

Solution 15:[15]

Swift 5

class OnboardingController: UIPageViewController {

    override init(transitionStyle style: UIPageViewController.TransitionStyle, navigationOrientation: UIPageViewController.NavigationOrientation, options: [UIPageViewController.OptionsKey : Any]? = nil) {
        super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        print("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}