PageViewController current page index in Swift

前端 未结 12 2102
你的背包
你的背包 2021-02-01 15:37

I want to get current index of a pageViewController, I don\'t know how I get the visible pages index.

func pageViewController(pageViewController: UIPageViewContr         


        
相关标签:
12条回答
  • 2021-02-01 16:21

    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
        }
    }
    
    0 讨论(0)
  • 2021-02-01 16:23

    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)
        }
    }
    
    0 讨论(0)
  • 2021-02-01 16:24

    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() }
    
    }
    
    0 讨论(0)
  • 2021-02-01 16:27

    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
                }
            }
        }
    }
    
    0 讨论(0)
  • 2021-02-01 16:32

    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)
    }
    
    0 讨论(0)
  • 2021-02-01 16:35

    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
    }
    
    0 讨论(0)
提交回复
热议问题