PageControll错误页数迅速4

时间:2018-06-28 09:33:57

标签: ios iphone swift xcode uipageviewcontroller

我创建了一个具有3个页面的PageController。我分配并声明了所有内容,实现了两个允许滚动视图的功能,同时我输入了命令以使控制器具有正确的页面报告。结果是,如果我的页面顺畅,一切正常,而页面计数器则按他的意愿工作..而我不明白哪里出了问题

problem problem2 problem3

        import UIKit
        import AVFoundation
        protocol IntroNavigationDelegate: class {
            func showNextViewController()
            func showPreviousViewController()
            var isPagingEnabled: Bool { get set }
        }
        final class IntroViewController: UIPageViewController, UIPageViewControllerDelegate, IntroNavigationDelegate, UIPageViewControllerDataSource {   
            func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
                if let viewControllerIndex = self.displayedControllers.index(of: viewController) {
                    if viewControllerIndex == 0 {
                    } else if viewControllerIndex == 1 {
                        return self.displayedControllers[viewControllerIndex - 1]
                    }
                }
                return nil
            }

            func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
                if let viewControllerIndex = self.displayedControllers.index(of: viewController) {

                    if viewControllerIndex < self.displayedControllers.count - 1 {
                        self.pageControl.currentPage = 1
                        return self.displayedControllers[viewControllerIndex + 1]
                    } else {
                        self.pageControl.currentPage = 0
                    }
                }
                return nil
            }

            var introRouter: IntroRouter?

            var pageControl = UIPageControl()

            var displayedControllers: [UIViewController] = []

            private var scrollView: UIScrollView? {
                for view in view.subviews {
                    if let subView = view as? UIScrollView {
                        return subView
                    }
                }
                return nil
            }

            var isPagingEnabled: Bool {
                get {
                    return scrollView?.isScrollEnabled ?? true
                }
                set {
                    scrollView?.isScrollEnabled = newValue
                }
            }

            override func viewDidLoad() {
                super.viewDidLoad()
                configurePageControl()
                setupUI()
                self.pageControl.updateCurrentPageDisplay()
                arrangeSubviews()
                self.delegate = self
            }

            override func viewWillAppear(_ animated: Bool) {
                self.navigationController?.setNavigationBarHidden(true, animated: animated)
            }

            override func viewWillDisappear(_ animated: Bool) {
                super.viewWillDisappear(animated)
                navigationController?.isNavigationBarHidden = false
            }

            func setDiplayedControllers(_ controllers: [UIViewController], visualizedController: UIViewController) {
                displayedControllers = controllers
                setViewControllers([visualizedController], direction: .forward, animated: false, completion: nil)
            }

            func showNextViewController() {
                if let current = viewControllers?.first, let next = IntroViewController(self, viewControllerAfter: current) {
                    setViewControllers([next], direction: .forward, animated: true, completion: nil)
                }
            }

            func showPreviousViewController() {
                if let current = viewControllers?.first, let previous = IntroViewController(self, viewControllerBefore: current) {
                    setViewControllers([previous], direction: .reverse, animated: true, completion: nil)
                }
            }

            func configurePageControl(){
                self.pageControl.frame = CGRect()
                self.pageControl.numberOfPages = self.displayedControllers.count
                self.pageControl.translatesAutoresizingMaskIntoConstraints = false
                self.pageControl.updateCurrentPageDisplay()

                self.view.addSubview(self.pageControl)
                pageControl.activate([
                    pageControl.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -20),
                    pageControl.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.1),
                    pageControl.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 1),
                    ])
            }

            override init(transitionStyle style: UIPageViewControllerTransitionStyle, navigationOrientation: UIPageViewControllerNavigationOrientation, options: [String : Any]? = nil) {
                super.init(transitionStyle: style, navigationOrientation: navigationOrientation, options: options)
                setup()
            }

            func setRouter(introRouter: IntroRouter) {
                self.introRouter = introRouter
            }

            required init?(coder aDecoder: NSCoder) {
                fatalError("init(coder:) has not been implemented")
            }

            private func setup() {
                view.backgroundColor = .white
                dataSource = self
            }
        }

        private extension IntroViewController {

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

                    if let viewControllerIndex = self.displayedControllers.index(of: viewController) {
                        if viewControllerIndex == 0 {
                            // wrap to last page in array
                            return self.displayedControllers.last
                        } else {
                            // go to previous page in array
                            return self.displayedControllers[viewControllerIndex + 1]
                        }
                    }
                    return nil
                }

                func IntroViewController(_ IntroViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
                    self.pageControl.updateCurrentPageDisplay()
                    if let viewControllerIndex = self.displayedControllers.index(of: viewController) {
                        if viewControllerIndex < self.displayedControllers.count - 1 {
                            // go to next page in array
                            self.pageControl.currentPage = viewControllerIndex
                            return self.displayedControllers[viewControllerIndex + 1]
                        } else {
                            // wrap to first page in array
                            self.pageControl.currentPage = viewControllerIndex
                            return self.displayedControllers.first
                        }
                    }
                    return nil
                }

            func IntroViewController(_ IntroViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {

        //         set the pageControl.currentPage to the index of the current viewController in pages
                if let viewControllers = IntroViewController.viewControllers {
                    if let viewControllerIndex = self.displayedControllers.index(of: viewControllers[0]) {
                        self.pageControl.currentPage = viewControllerIndex
                        self.pageControl.updateCurrentPageDisplay()
                    }
                }
            }

            func setupUI() {
                configurePageControl()
                pageControl.do {
                    $0.numberOfPages = 3
        //            $0.currentPage = 0
                    $0.pageIndicatorTintColor = .lightGray
                    $0.currentPageIndicatorTintColor = Theme.Colors.white
                    $0.currentPage = self.displayedControllers.count
                }
            }

            func arrangeSubviews() {
                view.addSubview(pageControl)
            }
        }

1 个答案:

答案 0 :(得分:0)

只需尝试以下代码。会很有帮助。

class PageViewModel: NSObject {

    private var timer: Timer?
    private var interval: Double?
    var enableAutoScroll: Bool = false {
        didSet {
            self.toggleTimer()
        }
    }
    var viewControllers: [UIViewController]
    var currentIndex: Int = 0
    var direction: UIPageViewControllerNavigationDirection = .forward

    init(viewControllers: [UIViewController]) {
        self.viewControllers = viewControllers
        super.init()
    }

    override convenience init() {
        self.init(viewControllers: [])
    }

    private func stopTimer() {
        if self.timer != nil {
            timer?.invalidate()
            timer = nil
            return
        }
    }

    private func startTimer() {

        if self.timer != nil {
            return
        }

        if #available(iOS 10.0, *) {
            if let time = interval {
                timer = Timer.scheduledTimer(withTimeInterval: time, repeats: true, block: { (timer: Timer) in
                    self.timerFire()
                })
            }
        } else {
            // Fallback on earlier versions
            if let time = interval {
                timer = Timer.scheduledTimer(timeInterval: time, target: self, selector: #selector(PageViewModel.timerFire), userInfo: nil, repeats: true)
            }
        }
    }

    @objc private func timerFire() {
        if direction == .forward {
            var index = currentIndex
            if index < self.viewControllers.count - 1 {
                index += 1
            } else {
                index = 0
            }

            currentIndex = index
            scrollToNextPage?(currentIndex)
            pageNumberChangedObserver?(currentIndex)

        } else {

            var index = currentIndex
            if index <= 0 {
                index = (self.viewControllers.count - 1)
            } else {
                index -= 1
            }
            currentIndex = index
            scrollToNextPage?(index)
            pageNumberChangedObserver?(currentIndex)
        }
    }


    // MARK: - Timer
    func toggleTimer() {
        if enableAutoScroll == true {
            startTimer()
        } else {
            stopTimer()
        }
    }

    fileprivate var scrollToNextPage: ((_ index: Int) -> Void)?
    func scrollToNextPage(callBack: @escaping (_ index: Int) -> Void) {
        scrollToNextPage = callBack
    }

    // MARK: - PageNumberChangedObserver
    fileprivate var pageNumberChangedObserver: ((_ index: Int) -> Void)?
    func pageNumberChanged(callBack: @escaping (_ index: Int) -> Void) {
        pageNumberChangedObserver = callBack
    }

}

// MARK: - UIPageViewControllerDataSource
extension PageViewModel: UIPageViewControllerDataSource {

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

        guard let viewControllerIndex = viewControllers.index(of: viewController) else {
            return nil
        }
        let previousIndex = viewControllerIndex - 1

        // User is on the first view controller and swiped left to loop to
        // the last view controller.
        guard previousIndex >= 0 else {
            //return orderedViewControllers.last
            // Uncommment the line below, remove the line above if you don't want the page control to loop.
            return nil
        }

        guard viewControllers.count > previousIndex else {
            return nil
        }

        return viewControllers[previousIndex]
    }

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

        let nextIndex = viewControllerIndex + 1
        let orderedViewControllersCount = viewControllers.count

        // User is on the last view controller and swiped right to loop to
        // the first view controller.
        guard orderedViewControllersCount != nextIndex else {
            //return orderedViewControllers.first
            // Uncommment the line below, remove the line above if you don't want the page control to loop.
            return nil
        }

        guard orderedViewControllersCount > nextIndex else {
            return nil
        }

        return viewControllers[nextIndex]
    }

}

// MARK: - UIPageViewControllerDelegate
extension PageViewModel: UIPageViewControllerDelegate {

    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {

        if let pageContentViewController = pageViewController.viewControllers?[0] {

            if let index = viewControllers.index(of: pageContentViewController) {
                currentIndex = index
                pageNumberChangedObserver?(currentIndex)
            }
        }
    }
}

在Container View Controller中编写以下代码:-

    // set current page to the page controller
    func setNextPage(index: Int, direction: UIPageViewControllerNavigationDirection) {

        if let firstViewController = pageViewModel?.viewControllers[selectedCategoryCell] {
            pageViewController?.setViewControllers([firstViewController],
                                                   direction: direction,
                                                   animated: true,
                                                   completion: nil)
        }
    }


 // MARK: - SET PAGE CONTROLLER's VIEW's
    private func setupPageViewController() {
        let pageViewController: UIPageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
        pageViewController.dataSource = pageViewModel
        pageViewController.delegate = pageViewModel
        if let firstViewController = pageViewModel?.viewControllers[selectedCategoryCell] {
            pageViewController.setViewControllers([firstViewController],
                                                  direction: .forward,
                                                  animated: true,
                                                  completion: nil)
        }

        for recognizer in pageViewController.gestureRecognizers {
            if recognizer is UITapGestureRecognizer {
                recognizer.isEnabled = false
            }
        }
        self.addChildViewController(pageViewController)
        self.containerView.addSubview(pageViewController.view)
        var pageViewRect = self.containerView.bounds
        if UIDevice.current.userInterfaceIdiom == .pad {
            pageViewRect = pageViewRect.insetBy(dx: 40.0, dy: 40.0)
        }
        pageViewController.view.frame = pageViewRect
        pageViewController.didMove(toParentViewController: self)
        self.pageViewController = pageViewController
    }


    // set the selected page and accordingly set the above collection view ( that is treatment option's collection view)
    func pageNumberChanged(index: Int) {
        self.selectedCategoryCell = index
    }

    // MARK: Init View Controller for Page Controller
    func initViewController(index: Int) -> UIViewController {
        guard let itemsViewController = self.storyboard?.instantiateViewController(withIdentifier: "MatchesV2ViewController") as? MatchesV2ViewController else {
            fatalError("Items View Controller Not Found")
        }
        itemsViewController.delegate = self
        itemsViewController.currentMatch = matches.user[index]
        return itemsViewController
    }

    // MARK: Setting VC In Page View Controller
    func instantiateViewControllers() {
        matchesScreen.removeAll()
        for i in 0..<matches.user.count {
            matchesScreen.append(initViewController(index: i))
        }
        pageViewModel = PageViewModel(viewControllers: matchesScreen)
        pageViewModel?.pageNumberChanged(callBack: { (index: Int) in
            self.pageNumberChanged(index: index)
        })
        pageViewModel?.scrollToNextPage(callBack: { (index: Int) in
            self.setNextPage(index: index, direction: .forward)
        })
        if matchesScreen.count > 0 {
            self.setupPageViewController()
        }
    }