To Infinity, And Not Beyond.
Thinking Differently… Again.
Disclaimer: This post assumes you’ve looked at and maybe even completed Part I.
There come times when writing software, where you need to rethink, refine and transform whatever it is you’re writing, in order to make it work with sudden — and often unexpected — curveball use cases. It’s never something to be feared, because your updated solution usually ends up better than the last commit. The previous post’s infinitely looping UIScrollView is no exception to that rule. While it would work for many — if not most — use cases, there will undoubtedly be those where it doesn’t whatsoever.
The catalyst behind this rethink, was a need to present different view controllers within a scrolling panel. Not just bog-standard, run-of-the-mill subviews, but full-blown view controllers. I suppose I could’ve just added the root views of each controller to the scroll view from before, but I considered that to be the quitter’s way out.
So I decided to think about everything differently. Let’s go to infinity, again.
You, Are, A, View Controllerrrrrrr!
Start off by opening Xcode and creating a new project, using the Single View Application template.
Then, open ViewController.swift and change its class to UIPageViewController. In the Storyboard, delete the lone UIViewController container you find there, and replace it with a UIPageViewController object. Make sure this new object is is the Initial View Controller and that the class is set to ViewController, as per the Swift file from above.
Now make sure the Page Controller’s “Navigation” is Horizontal, that the “Transition Style” is set to Scroll and that the “Spine Location” is set to None. You can of course set the navigation to Vertical if that floats your boat.
Create a new Swift file in Xcode, and call it Indexable and inside it, paste the following:
Back in the Storyboard, add two UIViewController containers to it. Give them unique background colours, such as .cyanColor() and .magentaColor(), and suitable Storyboard Identifiers such as “First” and “Second,” then save.
We’re using Associated Objects to mimic stored properties in a Swift extension. This allows us to add an id property to every UIViewController instance in our app. Feel free to make this a String or even some kind of enum value, but I’m just going to use Int to keep things simple.
Son of a building block! It’s happening!
After this, in your ViewController.swift file, replace the contents with the following:
Because our view controller is our delegate and our dataSource, all the fetching and displaying of View Controller’s based on the index is done here. You can of course externalise these into other objects/files.
If you run the app now, you’ll notice that it works, but there’re no dots to indicate the current page. As I mentioned in my last post, I feel rather strongly that the UIPageControl exists for a darn-good reason, and that you should always use it, and we…will be, in a moment.
A UIPageControl!? No Way!
One thing you’ll notice if you use the two provided UIPageViewControllerDelegate methods to add a UIPageControl to the screen, is that it has a dirty great .blackColor() background on it.
It’s ugly, and multiple kinds of terrible. I hated it because it didn’t go with my design at all. So I had to find another way around it.
First, add a UIPageControl variable to your class. Then, we’ll use the following delegate method to update it:
After you do that, it’ll work, but it won’t be anywhere on the screen. Kind of pointless really, so let’s fix that.
Open up the storyboard and add a UIPageControl to your UIPageViewController’s container, then wire it up to your outlet. Set the number of pages to 2 for the purposes of this tutorial.
Add these lines to your viewDidLoad() function:
And there you have it.
The didFinishAnimating method is brilliant for our purpose because it has a previousViewControllers array. This is despite UIPageViewController seemingly only able to support the one view controller at a time. You can use this array and check the kind of UIViewController that it holds, and use that to update your UIPageControl accordingly. We’re using a switch on our newly added id to determine which dot to highlight, so you’ll need to rethink this method so as to make it support your setup.
All in all, a vastly simpler setup this time around. Although it is much more powerful and certainly capable of doing so much more.
At jtribe, we proudly craft software solutions for iOS, Android and Web and are passionate about our work. We’ve been working with the iOS and Android platforms since day one, and are one of the most experienced mobile development teams in Australia. We measure success on the impact we have, and with over six-million end users we know our work is meaningful, and this continues to be our driving force.