Onboarding Screens in iOS

Henry Chukwu
The Startup
Published in
5 min readFeb 14, 2021

Most apps these days come with onboarding screens so we are going to try and create one for our app.

Setup

First we have our onboarding viewcontroller then drag a container View(found only in storyboards), onto the viewcontroller and two buttons(going to serve as our skip and next Buttons)

Drage a page view controller on to the storyboard then control + drag from the container view to the page view controller and click on embed the page view controller in the container view so on viewdidload the pageView controller will appear inside the container view. Create a file called OnboardingPageViewController and set it as the custom class of the page controller you created in storyboard.

Under the attributes inspector of your page controller change the transition style of your page control to Scroll

In OnboardingPageViewController create a delegate called onboardingPageViewControllerDelegate with two functions setupPageController and turnPageController. Set the delegate and dataSource of the pagecontroller to self then create an extension of OnboardingPageViewController and conform it to the UIPageViewControllerDataSource protocol like so

Create a file called OnboardingContentViewController and set it as the custom class of a new viewcontroller in storyboard, we will come back to this.

Go back to OnboardingPageViewController and replace with this code

protocol onboardingPageViewControllerDelegate: class {func setupPageController(numberOfPage: Int)func turnPageController(to index: Int)}class OnboardingPageViewController: UIPageViewController {weak var pageViewControllerDelagate: onboardingPageViewControllerDelegate?var currentIndex = 0override func viewDidLoad() {super.viewDidLoad()dataSource = selfdelegate = self}}extension OnboardingPageViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate {func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {if var index = (viewController as? OnboardingContentViewController)?.index {index -= 1return contentViewController(at: index)}return nil}func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {if var index = (viewController as? OnboardingContentViewController)?.index {index += 1return contentViewController(at: index)}return nil}func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {if let pageContentViewController = pageViewController.viewControllers?.first as? OnboardingContentViewController {currentIndex = pageContentViewController.indexself.pageViewControllerDelagate?.turnPageController(to: currentIndex)}}func contentViewController(at index: Int) -> OnboardingContentViewController? {return nil}}

In your prepare(for segue ) function in OnboardingViewController add onBoardingViewController.pageViewControllerDelagate = self, then add this

extension OnboardingViewController: onboardingPageViewControllerDelegate {func setupPageController(numberOfPage: Int) {pageControl.numberOfPages = numberOfPage}func turnPageController(to index: Int) {pageControl.currentPage = index}}

So your OnboardingViewController looks like this

import UIKitclass OnboardingViewController: UIViewController {@IBOutlet weak var pageControl: UIPageControl!@IBOutlet weak var skipButton: UIButton!@IBOutlet weak var nextButton: UIButton!weak var onBoardingPageViewController: OnboardingPageViewController?override func viewDidLoad() {super.viewDidLoad()// Do any additional setup after loading the view.}@IBAction func skipButtonTapped(_ sender: Any) {}@IBAction func nextButtonTapped(_ sender: Any) {}override func prepare(for segue: UIStoryboardSegue, sender: Any?) {if let onBoardingViewController = segue.destination as? OnboardingPageViewController {onBoardingViewController.pageViewControllerDelagate = selfonBoardingPageViewController = onBoardingViewController}}}extension OnboardingViewController: onboardingPageViewControllerDelegate {func setupPageController(numberOfPage: Int) {pageControl.numberOfPages = numberOfPage}func turnPageController(to index: Int) {pageControl.currentPage = index}}

OR This

Add this to viewDidLoad of OnboardingPageViewController

if let firstViewController = contentViewController(at: 0) {setViewControllers([firstViewController], direction: .forward, animated: true, completion: nil)}

We have left OnboardingContentViewController for a while now, let;s go back there and finish that up.

Add a UIImage and a UILabel to OnboardingContentViewController in storyboard and constrain them. Connect them to IBOutlets like so.

Update your OnboardingContentViewController to this

class OnboardingContentViewController: UIViewController {@IBOutlet weak var contentImageView: UIImageView!@IBOutlet weak var titleLabel: UILabel! {didSet {titleLabel.numberOfLines = 0}}var index = 0var heading = “”var subHeading = “”var image = UIImage()var bgColor = UIColor()override func viewDidLoad() {super.viewDidLoad()setupTextLabel()contentImageView.image = imageview.backgroundColor = bgColor}func setupTextLabel() {let attributedText = NSMutableAttributedString(string: heading, attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 15),NSAttributedString.Key.foregroundColor: UIColor.white])attributedText.append(NSAttributedString(string: “\n\n\(subHeading)”, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13), NSAttributedString.Key.foregroundColor: UIColor.white]))titleLabel.attributedText = attributedTexttitleLabel.textAlignment = .center}}

Add this variables to OnboardingPageViewController

var pageTitle = [“First Page”, “Second Page”, “Third Page”]var pageImages: [UIImage] = []var pageDescriptionText = [“This is first page stating what this app is about”, “A second page stating more app info incase you need them”, “The very last page with yet more info for our esteem users”]var backgroundColor : [UIColor] = [.blue, .green, .red]

Make sure you update the pageImages variable with suitable images. Now update contentViewController to

func contentViewController(at index: Int) -> OnboardingContentViewController? {if index < 0 || index >= pageTitle.count {return nil}let storyBoard = UIStoryboard(name: “Main”, bundle: nil)if let pageContentViewController = storyBoard.instantiateViewController(withIdentifier: “onboardingContentVC”) as? OnboardingContentViewController {pageContentViewController.image = pageImages[index]pageContentViewController.subHeading = pageDescriptionText[index]pageContentViewController.heading = pageTitle[index]pageContentViewController.bgColor = backgroundColor[index]pageContentViewController.index = indexself.pageViewControllerDelagate?.setupPageController(numberOfPage: 3)return pageContentViewController}return nil}

Run your app and see what we have done so far. You can modify these further, for example, your skip and next buttons were not attended to here those can be completed to carter for their use cases.

Now we’re done. You can find the source code here.

--

--