Form entry is never fun. Especially on a mobile device. In our app here at WeVat, we do require the user to enter some of their details manually, so we are striving to make that as painless for the user as possible!
One thing we have recently implemented is a simple progress view to subtly show the users how far through the process they are.
I will be showing you how to code up this progress view in a generic way, so you can drop it into your UINavigationController
and be done with it! So let’s get started.
TL;DR
Just want the code? No beef! Download the sample project here.
I have set up a new project in Xcode with a stack of four UIViewControllers
in a UINavigationController
. Each has their own next button, which will push segue to the next view controller, and a finish button which will take you back to the beginning with an unwind segue.
Our basic navigation flow
As mentioned in my previous articles, we try to ‘componentise’ bits of functionality as much as possible through the use of protocols. So lets create a protocol which will handle the displaying of the UIProgressView
.
Once we have this, we can use protocol extensions to provide some default behaviour in how we want this view configured. We will need to ensure the view is added to its superview and laid out correctly. Be sure to pin the view to the navigationBar
property of the UINavigationController
By further extending for UINavigationController
, we can provide views to the protocol to give a default behaviour for all navigation controllers that implement this. Man I love protocol extensions.
We can now create our subclass of UINavigationController
and implement our protocol here to add this functionality to all of the view controllers in our navigation stack. Don’t forget to add this as the custom class in the storyboard.
Okay so now we have the UIProgressView
in our navigation bar, but how are we going to update the progress for each of the view controllers you ask?
We can create another protocol to handle this functionality. I will talk you through what each of these functions will provide.
updateProgress
with simply a float and animation Bool
. We will pass this through to the underlying UIProgressView.setProgress
later.updateProgress
with an array of UIViewController types. This may look a bit strange, but this can give us a way to update progress based on all view controllers within a navigation stack. I will show you why this is useful below.completeProgress
fills the progress bar to full.Here we can extend the ProgressViewUpdater
to work out what the actual progress is. We do this by iterating through our view controllers and working out the progress based on where in the stack we currently are.
We are nearly there! Just one more thing and we have a fully functioning progress view within our flow.
For our view controllers, we can make it really simple to pass the navigation controller the information we need. And guess what is coming next, more protocols!
We can conform to our ProgressViewUpdater
protocol and provide a cleaner interface for our view controllers within this flow.
Then, this gives us the ability to programatically define within the implementation of this function, each view controller in our navigation stack, in the order they appear in.
Ensure our view controllers conform to MainFormProgressViewUpdater
and we can simply call updateProgress()
to update the progress view based on where we are in the flow.
If you wanted to have another flow within your application with a similar functionality, all you would need to do is create another protocol similar to MainFormProgressUpdater
and drop it in to your view controllers.
Note: Be sure to call it from _viewDidAppear_
to see the animation.
I had fun making this one! Do let me know what you think, or if you would do it any differently.
And be sure to check out my previous articles for similar iOSy goodness.