skip to Main Content

I have three classes OnboardingViewController, OnboardingPageViewController, and OnboardingContentViewController.
In my ViewController class, I have a UIPageControl that updates whenever I press the UIButton "Next" beneath it. This is working as intended. However I want to make the UIPageControl updated according to when I swipe left/right on the UIPageViewController, but I’m not sure how to do this.

class OnboardingViewController: UIViewController {

    @IBOutlet weak var nextButton: UIButton!
    @IBOutlet weak var pageControl: UIPageControl!
    
    var onboardingPageViewController: OnboardingPageViewController?
    
    @IBAction func nextButtonTapped(_ sender: UIButton) {
        if let index = onboardingPageViewController?.currentPageIndex {
            switch index {
            case 0:
                onboardingPageViewController?.nextPage()
            case 1:
                onboardingPageViewController?.nextPage()
                nextButton.setTitle("Get Started", for: .normal)
            case 2:
                //present login ViewController after final next button is tapped
            default:
                break
            }
            pageControl.currentPage = index + 1
        }
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let destination = segue.destination
        if let pageViewController = destination as? OnboardingPageViewController {
            onboardingPageViewController = pageViewController
        }
    }
}
class OnboardingContentViewController: UIViewController {
    @IBOutlet var imageView: UIImageView!
    @IBOutlet var titleLabel: UILabel! 
    @IBOutlet var introLabel: UILabel!

    var index = 0
    var contentTitle = ""
    var intro = ""
    var imageFile = ""
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        titleLabel.text = contentTitle
        introLabel.text = intro
        imageView.image = UIImage(named: imageFile)
    }
}
class OnboardingPageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
    
    var pageTitle = ["Title1", "Title2", "Title3"]
    var pageIntro = ["Description1","Description2","Description3"]
    var pageImages = ["image1","image2","image3"]
    var currentPageIndex = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        dataSource = self
        delegate = self
        
        if let startingViewController = contentViewController(at: currentPageIndex) {
            setViewControllers([startingViewController], direction: .forward,animated: true, completion: nil)
        }
    }
    
    func nextPage() {
        currentPageIndex += 1
        if let nextViewController = contentViewController(at: currentPageIndex){
            setViewControllers([nextViewController], direction:.forward, animated: true, completion:nil)
        }
    }
   
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        var index = (viewController as! OnboardingContentViewController).index
        index -= 1
        return contentViewController(at:index)
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        var index = (viewController as! OnboardingContentViewController).index
        index += 1
        return contentViewController(at:index)
    }
    
    func contentViewController(at index: Int) -> OnboardingContentViewController? {
        if index < 0 || index >= pageIntro.count {
            return nil
        }
        
        let storyboard = UIStoryboard(name: "Onboarding", bundle: nil)
        if let pageContentViewController = storyboard.instantiateViewController(withIdentifier:"OnboardingContentViewController") as? OnboardingContentViewController {
                pageContentViewController.imageFile = pageImages[index]
                pageContentViewController.contentTitle = pageTitle[index]
                pageContentViewController.intro = pageIntro[index]
                pageContentViewController.index = index
                return pageContentViewController
        }
            return nil
    }

}

I tried adding the UIPageViewController delegate method to the first view controller but I’m finding that nothing is printing in the console. What am I missing?

class OnboardingViewController: UIViewController, UIPageViewControllerDelegate {

    @IBOutlet weak var pageControl: UIPageControl!

 override func viewDidLoad() {
        super.viewDidLoad()
        
        let pageController = self.storyboard!.instantiateViewController(withIdentifier: "OnboardingPageViewController") as! UIPageViewController
        pageController.delegate = self
        
    }

 func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        if completed == true {
            print("change page control number")
        }
    }

enter image description here

2

Answers


  1. Easiest way to create a post notification Here

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        var index = (viewController as! OnboardingContentViewController).index
        index -= 1
        // post notification here with sending index value
        return contentViewController(at:index)
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        var index = (viewController as! OnboardingContentViewController).index
        index += 1
        // post notification here with sending index value
        return contentViewController(at:index)
    }
    

    And listen in viewDidLoad of OnboardingViewController

    Login or Signup to reply.
  2. When you do let pageController = self.storyboard!.instantiateViewController..., you’re initializing a new copy of the page view controller. This is unrelated to the one that your users see.

    /// no!
    let pageController = self.storyboard!.instantiateViewController(withIdentifier: "OnboardingPageViewController") as! UIPageViewController
    pageController.delegate = self
    

    Instead, you need to reference the existing page view controller that was added in the storyboard. It’s automatically added as the first child of OnboardingViewController, so you can get it using self.children[0].

    class OnboardingViewController: UIViewController, UIPageViewControllerDelegate {
        
        @IBOutlet weak var pageControl: UIPageControl!
        
        /// here!
        var pageController: UIPageViewController {
            return self.children[0] as! UIPageViewController
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
            pageController.delegate = self
        }
        
        func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
            if completed == true {
                print("change page control number")
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search