なんとかするから、なんとかなる

エンジニア関係のことを書きます

iOS UIPageViewController How to soleve the error message "Unbalanced calls to begin/end appearance transitions for" .

Introduction

When I tried to transition some pages so rapidly.

The Xcode shows an error message as below.

Unbalanced calls to begin/end appearance transitions for 

The code is below.

class MyPageViewController: UIPageViewController {
    var maxPage = 3
    var currentPage = 0

    ~~~~
    // SomeCode....
    ~~~~
}

extension MyPageViewController: UIPageViewControllerDataSource {
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard self.currentPage > self.maxPage else { return nil }
        self.currentPage += 1
        
        let myAfterVC = MyAfterViewController()
        
        return myAfterVC
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard self.currentPage >=  0 else { return nil }
        self.currentPage -= 1
        
        let myBeforeVC = MyBeforeViewController()
        
        return myBeforeVC
    }
}

Why

This error message is showed up when a new transition begin before an old old is not completed.

Solution

To prepend a new transition before an old one is not completed, I added a transitioning flag in MyPageViewController and change the value in UIPageVieController Delegate.

The true code is below.

class MyPageViewController: UIPageViewController {
    var isTransitioning = false
    var maxPage = 3
    var currentPage = 0

    ~~~~
    // SomeCode....
    ~~~~
}

extension MyPageViewController: UIPageViewControllerDataSource {
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard self.currentPage < self.maxPage, self.isTransitioning == false else { return nil }
        self.currentPage += 1
        
        let myAfterVC = MyAfterViewController()
        
        return myAfterVC
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard self.currentPage >=  0, self.isTransitioning == false else { return nil }
        self.currentPage -= 1
        
        let myBeforeVC = MyBeforeViewController()
        
        return myBeforeVC
    }
}


extension MyPageViewController: UIPageViewControllerDelegate {
    func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
        self.isTransitioning = true
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        self.isTransitioning = false
    }
}