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")
}
}
2
Answers
Easiest way to create a post notification Here
And listen in
viewDidLoad
ofOnboardingViewController
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.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 usingself.children[0]
.