Reputation: 177
I want to use the cool swipe animation between screens - UIPageViewController
(yes, you know the style from the intro screen), but all the code I found on the Internet and Github was useless for me.
I found demos with just one UIViewController
in the Storyboard
interface and almost all the apps showed how to change an image source from an array. I read the Apple reference, but I do not understand it.
I need a few ViewControllers
on my Storyboard
(I want to design all the screens in the UIPageViewController
differently, they will be connected to own ViewControllers
classes) who will be presented in the UIPageViewController
.
Or of course if you know a better way how do that please say so! But I need the feature that if you swipe, the screen moves with you.
Does someone know how to do that?
Upvotes: 1
Views: 900
Reputation: 437372
There's nothing in UIPageViewController
that requires the various view controllers to be same class. So, just implement viewControllerBeforeViewController
and viewControllerAfterViewController
that return different types of view controllers. If you want to reference child view controllers from the storyboard, just give those scenes unique storyboard ids, and then you can use instantiateViewControllerWithIdentifier
. You might, for example, have an array of storyboard identifiers, and use that to determine which type of scene is "before" and "after" the current one.
There are tons of ways of implementing this, but you could do something like:
class ViewController: UIPageViewController, UIPageViewControllerDataSource {
let identifiers = ["A", "B", "C", "D"] // the storyboard ids for the four child view controllers
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
setViewControllers([viewControllerForPage(0)!], direction: .Forward, animated: false, completion: nil)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
var page = (viewController as PageDelegate).pageNumber + 1
return viewControllerForPage(page)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
var page = (viewController as PageDelegate).pageNumber - 1
return viewControllerForPage(page)
}
func viewControllerForPage(page: Int) -> UIViewController? {
if page >= 0 && page < identifiers.count {
let controller = storyboard?.instantiateViewControllerWithIdentifier(identifiers[page]) as? UIViewController
(controller as PageDelegate).pageNumber = page
return controller
}
return nil
}
}
Clearly, if you wanted to be more elegant here, you could maintain a cache of previously instantiated view controllers, but make sure you respond to memory pressure and purge that cache if necessary. But hopefully this illustrates the fact that there's nothing about page view controllers that dictates that the children are a particular class of controller.
By the way, the above assumes that each of the child view controllers conforms to a protocol to keep track of the page number.
/// Page delegate protocol
///
/// This is a protocol implemented by all of the child view controllers. I'm using it
/// just to keep track of the page number. In practical usage, you might also pass a
/// reference to a model object, too.
@objc protocol PageDelegate {
var pageNumber: Int { get set }
}
If you want to go a completely different direction, another approach is to use standard storyboard where you have segues that present one view controller after another, and then for each view controller implement swipe gesture recognizers, where swiping from the right performs the segue to transition to the next scene (e.g. an IBAction
that does performSegueWithIdentifier
), and another swipe gesture recognizer (left to right) will dismiss the view controller.
Finally, if you want these gesture recognizers to be interactive (e.g. to follow along with the user's finger), you could use custom transitions, combined with interactive transitions. For more information, see WWDC 2013 video Custom Transitions Using View Controllers or WWDC 2014 videos View Controller Advancements in iOS 8 (which, about 20 minutes into the video, describes how custom transitions have been enhanced in iOS 8 with presentation controllers) and A Look Inside Presentation Controllers.
Upvotes: 4
Reputation: 7466
I think you might take advantage of View Controller Containment. We are dealing with 4 elements at play here.
You would add the scroll view and the page control as the main view controller's properties. The main controller would handle the scrolling logic, basically syncing the horizontal scrolling between the scrollview and the page control. The contents of the scroll view would be constituted by root views of all the detail view controllers.
Upvotes: 0