5

I want to detect the current page in order to modify a button's title while the last page is showing and re-modify every time the user swipes back from the last to the second to last page.

Now these are my delegate methods and my array of ViewControllers:

lazy var VCArr: [UIViewController] = {
    let firstVC = self.storyboard!.instantiateViewController(withIdentifier: "FirstTutorialPage")
    let secondVC = self.storyboard!.instantiateViewController(withIdentifier: "SecondTutorialPage")
    let thirdVC = self.storyboard!.instantiateViewController(withIdentifier: "ThirdTutorialPage")
    let fourthVC = self.storyboard!.instantiateViewController(withIdentifier: "FourthTutorialPage")
    return [firstVC, secondVC, thirdVC, fourthVC]
}()

delegate methods

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {

    guard let viewControllerIndex = self.VCArr.index(of: viewController) else {
        return nil
    }

    let previousIndex = viewControllerIndex - 1

    guard previousIndex >= 0 else {
        return nil
    }

    guard self.VCArr.count > previousIndex else {
        return nil
    }

    return self.VCArr[previousIndex]
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
    guard let viewControllerIndex = self.VCArr.index(of: viewController) else {
        return nil
    }

    let nextIndex = viewControllerIndex + 1

    guard nextIndex < self.VCArr.count else {
        return nil
    }

    guard self.VCArr.count > nextIndex else {
        return nil
    }

    return self.VCArr[nextIndex]
}

Can someone help me detect with accuracy the last page shown? I tried some methods but everyone of them showed me the wrong index. Those methods detected the last index while showing the second to last page.

Thanks to all.

Elia Crocetta
  • 318
  • 1
  • 6
  • 20

5 Answers5

11

My solution consist in implementing the function pageViewController(_:didFinishAnimating:previousViewControllers:transitionCompleted:) of the UIPageViewControllerDelegate and doing the following:

if completed {
    if let currentViewController = pageViewController.viewControllers?.first,
    let index = pages.index(of: currentViewController) {
        currentIndex = index
    }
}

where pages is a property of my page view controller where I store all my view controllers to be presented and currentIndex is a property to keep track of the index of the current page (aka view controller) in order to use it in other parts of my code.

Francesco
  • 349
  • 5
  • 10
0

Try get the first view controller in pageViewController.viewControllers

    if let vc = pageViewController.viewControllers?[0] {
        ... vc is current controller...
    }

If you want to handle page changes, do it in a delegate method:

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
    if let vc = pageViewController.viewControllers?[0] {
        ... vc is current controller...
    }
}
0

Try this delegate method.

var currentIndex = 0

func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
    guard let nextViewController = pendingViewControllers[0] as? ViewController else { return }
    self.currentIndex = nextViewController.index
}
nao
  • 165
  • 1
  • 3
0

Set up the didFinishAnimating pageViewController DataSource function like so. Store a property of your data source. In this case I named it orderedViewControllers. Then as you swipe, the current index will be printed to the console.

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
    let pageContentViewController = pageViewController.viewControllers![0]
    let index = orderedViewControllers.index(of: pageContentViewController)!
    print(index)
}
-1

Here you have the way to calculate index of previous and next item by using % operator

let nextIndex = (viewControllerIndex + 1) % VCArr.count
let previousIndex = (VCArr.count + viewControllerIndex - 1) % VCArr.count
Szu
  • 2,254
  • 1
  • 21
  • 37
  • It doesn't works properly. First of all, this method allows to swipe repeatedly, then when I swipe forward the index printed is "1 3 2", and just one view is viewed. – Elia Crocetta Aug 07 '17 at 19:01
  • How to detect last page? You just compare next/previous index with `VCArr.count-1`. If you want to change button text give us more code and give more details. – Szu Aug 07 '17 at 19:46
  • I want to know if there's a method that detects with accuracy which viewcontroller embedded in a UIPageViewController is shown. For instance, when the user swipes left or right, I want to know exactly which viewController of my array (VCArr) is shown, in order to change the title of the button from "next" to "start", and again from "start" to "next" if the user swipes from the last to the second to last page. I hope I expressed myself better. – Elia Crocetta Aug 07 '17 at 19:52