Search code examples
iosswiftswipeuipageviewcontroller

uipageviewcontroller disable right swipe


I have a uipageviewcontroller with four individual view controllers in it. I want to disable the right swipe action for the first view controller and disable the left swipe action for the fourth view controller. When the app launches, I want the user to only be able to swipe left and not right, because swiping right, takes the user to the fourth view controller and swiping left on the fourth view controller takes the user to the first view controller. Here is my code.

class TutorialPageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
    weak var tutorialDelegate: TutorialPageViewControllerDelegate?

    lazy var VCArr: [UIViewController] = {
        return [self.VCInstance(name: "FirstVC"),
                self.VCInstance(name: "SecondVC"),
                self.VCInstance(name: "ThirdVC"),
                self.VCInstance(name: "FourthVC")]

    }()

    private func VCInstance(name: String) -> UIViewController {
        return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: name)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let pageControl = UIPageControl.appearance()
        //Customizing
        pageControl.pageIndicatorTintColor = UIColor.lightGray
        pageControl.currentPageIndicatorTintColor = UIColor(red:0.23, green:0.73, blue:1.00, alpha:1.0)

        dataSource = self
        delegate = self
        self.dataSource = self
        self.delegate = self

        if let FirstVC = VCArr.first {
            setViewControllers([FirstVC], direction: .forward, animated: true, completion: nil)
            tutorialDelegate?.tutorialPageViewController(tutorialPageViewController: self, didUpdatePageCount: VCArr.count)

        }
    }

   override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        for view in self.view.subviews {
            if view is UIScrollView {
                view.frame = UIScreen.main.bounds
            } else if view is UIPageControl {
                view.backgroundColor = UIColor.clear
            }
        }
    }

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

        let previousIndex = viewControllerIndex - 1

        guard previousIndex >= 0 else {
            return VCArr.last
        }

        guard VCArr.count > previousIndex else {
            return nil
        }
        return VCArr[previousIndex]
    }

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

        let nextIndex = viewControllerIndex + 1

        guard nextIndex < VCArr.count else {
            return VCArr.first
        }

        guard VCArr.count > nextIndex else {
            return nil
        }
        return VCArr[nextIndex]
    }

    public func presentationCount(for pageViewController: UIPageViewController) -> Int {
        return VCArr.count
    }


    public func presentationIndex(for pageViewController: UIPageViewController) -> Int {
        guard let firstViewController = viewControllers?.first,
        let firstViewControllerIndex = VCArr.index(of: firstViewController) else {
             return 0
         }
         return firstViewControllerIndex
     }
}

extension TutorialPageViewController {

    func pageViewController(pageViewController: UIPageViewController,
                            didFinishAnimating finished: Bool,
                            previousViewControllers: [UIViewController],
                            transitionCompleted completed: Bool) {
        if let firstViewController = viewControllers?.first,
            let index = VCArr.index(of: firstViewController) {
            tutorialDelegate?.tutorialPageViewController(tutorialPageViewController: self, didUpdatePageIndex: index)
        }
    }

}

Solution

  • Basically you need to change following lines

    guard previousIndex >= 0 else {
                return nil
            }
    
    
    guard nextIndex < VCArr.count else {
                return nil
            }
    

    ----- OR -----

    Change viewControllerAfter as

     public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
                guard let viewControllerIndex = VCArr.index(of: viewController) else {
                    return nil
                }
    
                let nextIndex = viewControllerIndex + 1
    
                guard nextIndex < VCArr.count else {
                return nil
            }
    
                guard VCArr.count > nextIndex else {
                    return nil
                }
    
                return VCArr[nextIndex]
            }
    

    Change ViewControllerBefore as

    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
            guard let viewControllerIndex = VCArr.index(of: viewController) else {
                return nil
            }
    
            let previousIndex = viewControllerIndex - 1
    
           guard previousIndex >= 0 else {
                return nil
            }
            guard VCArr.count > previousIndex else {
                return nil
            }
            return VCArr[previousIndex]
        }