I want to get current index of a pageViewController, I don\'t know how I get the visible pages index.
func pageViewController(pageViewController: UIPageViewContr
Swift 3: full programmatic PageViewController example to get/set the current page index without view tagging:
enum PageViewType:String {
case green = "greenView"
case blue = "blueView"
case red = "redView"
}
class MyPageViewController: UIPageViewController {
private (set) lazy var orderedViewControllers:[UIViewController] = {
return [self.newPageView(.green),
self.newPageView(.blue),
self.newPageView(.red)
]
}
var currentIndex:Int {
get {
return orderedViewControllers.index(of: self.viewControllers!.first!)!
}
set {
guard newValue >= 0,
newValue < orderedViewControllers.count else {
return
}
let vc = orderedViewControllers[newValue]
let direction:UIPageViewControllerNavigationDirection = newValue > currentIndex ? .forward : .reverse
self.setViewControllers([vc], direction: direction, animated: true, completion: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
dataSource = self
if let firstViewController = orderedViewControllers.first {
setViewControllers([firstViewController],
direction: .forward,
animated: true,
completion: nil)
}
}
private func newPageView(_ viewType:PageViewType) -> UIViewController {
let vc = self.storyboard?.instantiateViewController(withIdentifier: viewType.rawValue)
return vc
}
}
UIPageViewController DataSource implementation:
extension MyPageViewController:UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let previousIndex = currentIndex - 1
guard previousIndex >= 0 else {
return nil
}
guard orderedViewControllers.count > previousIndex else {
return nil
}
return orderedViewControllers[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let nextIndex = currentIndex + 1
guard orderedViewControllers.count != nextIndex else {
return nil
}
guard orderedViewControllers.count > nextIndex else {
return nil
}
return orderedViewControllers[nextIndex]
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return orderedViewControllers.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return currentIndex
}
}
You can use next method:
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
guard
completed,
let viewControllerIndex = tutorialViews.index(of: pageViewController.viewControllers!.first!) else
return
}
self.currentIndex = viewControllerIndex
}
Where tutorialViews is an array of pages (ViewControllers).
And initialize currentIndex like that:
var currentIndex = 0 {
didSet {
self.updateContentForPage(withIndex: currentIndex)
}
}
First, have your UIPageViewController implement the UIPageViewControllerDataSource method presentationIndex(for pageViewController: UIPageViewController) -> Int
to return the index for each of the PageViewController's ViewControllers.
Then in your delegate, access the datasource through the passed-in PageViewController:
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
guard let dataSource = pageViewController.dataSource,
let currentIndex = dataSource.presentationIndex?(for: pageViewController) else { preconditionFailure() }
}
Swift 4 version
Extending the ViewController class with these protocols (UIPageViewControllerDelegate
, UIPageViewControllerDataSource
) and adding the following functions helped me to make my page control work correctly.
class ViewController : UIPageViewControllerDelegate,UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
if let viewController = pendingViewControllers[0] as? DataViewController {
self.lastPendingViewControllerIndex = viewController.index!
}
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed {
pageControl.currentPage = self.lastPendingViewControllerIndex
if lastPendingViewControllerIndex == 4 {
self.getstartedButton.isHidden=false
} else {
self.getstartedButton.isHidden=true
}
}
}
}
Just check apple's docs (https://developer.apple.com/tutorials/swiftui/interfacing-with-uikit) -> Section 3 -> Step 5
You can get the current index like this
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed,
let visibleViewController = pageViewController.viewControllers?.first,
let index = parent.controllers.firstIndex(of: visibleViewController)
{
parent.currentPage = index
}
}
or if you are keeping viewControllers in an array you can do this
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed,
let visibleViewController = pageViewController.viewControllers?.first,
let index = orderedViewControllers.firstIndex(of: visibleViewController)
{
statisticsPageDelegate?.statisticsPageViewController(statisticsPageViewController: self, didUpdatePageIndex: index)
}
}
This is the full code
class StatisticsPageViewController: UIPageViewController,UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var currentIndex: Int?
var statisticsPageDelegate: StatisticsPageViewControllerDelegate?
private var pendingIndex: Int?
required init?(coder aDecoder: NSCoder) {
super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
dataSource = self
delegate = self
if let firstViewController = orderedViewControllers.first {
setViewControllers([firstViewController],
direction: .forward,
animated: true,
completion: nil)
}
statisticsPageDelegate?.statisticsPageViewController(
statisticsPageViewController: self,
didUpdatePageCount: orderedViewControllers.count
)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.index(of:viewController) else {
return nil
}
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else {
return nil
}
guard orderedViewControllers.count > previousIndex else {
return nil
}
return orderedViewControllers[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.index(of:viewController) else {
return nil
}
let nextIndex = viewControllerIndex + 1
let orderedViewControllersCount = orderedViewControllers.count
guard orderedViewControllersCount != nextIndex else {
return nil
}
guard orderedViewControllersCount > nextIndex else {
return nil
}
return orderedViewControllers[nextIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed,
let visibleViewController = pageViewController.viewControllers?.first,
let index = orderedViewControllers.firstIndex(of: visibleViewController)
{
statisticsPageDelegate?.statisticsPageViewController(statisticsPageViewController: self, didUpdatePageIndex: index)
}
}
private(set) lazy var orderedViewControllers: [UIViewController] = {
return [self.newStatisticsViewController(identifier: Identifiers.PROGRAM_VIEW_CONTROLLER),
self.newStatisticsViewController(identifier: Identifiers.LOGIN_VIEW_CONTROLLER)]
}()
private func newStatisticsViewController(identifier: String) -> UIViewController {
return UIStoryboard(name: "Main", bundle: nil) .
instantiateViewController(withIdentifier: identifier)
}
}
protocol StatisticsPageViewControllerDelegate: class {
func statisticsPageViewController(statisticsPageViewController:
StatisticsPageViewController, didUpdatePageCount count: Int)
func statisticsPageViewController(statisticsPageViewController:
StatisticsPageViewController, didUpdatePageIndex index: Int)
}
Add this code to your UIPageViewController
.
var pages = [UIViewController]()
var currentIndex: Int {
guard let vc = viewControllers?.first else { return 0 }
return pages.firstIndex(of: vc) ?? 0
}