UIPageViewController curl transition bug since iOS 16

The effect I'm trying to achieve: https://imgur.com/pyaZlen.

Basically, a simultaneous page curl and translation on the x axis (since the video was registered in landscape, the translation appears on the y axis).

The page curl animation is performed under the hood whenever setViewControllers method of UIPageViewController is called, while the translation is achieved through UIView.animate by updating constraints.

Until iOS 15, this was perfectly fine, however since iOS 16 the animation is laggy and does not work as intended, see below.

  1. Regular page curl transition (no translation): https://imgur.com/4CQ3KU8 - the back side of the page is fully visible. This was also the behaviour with translation on iOS 14 and 15.
  2. Page curl with translation: https://imgur.com/guMolIe - the back side of the page is partially transparent.

The issue is clearly related to the x translation occurring while the curl animation is being performed, as without it everything works fine. Probably this is not the right way to perform multiple animations I assume, however since the page curl happens under the hood I'm not really sure on how to handle it.

My question is: how can I achieve a page curl and x translation animations simultaneously? And on a side note, does anyone knows why the strange behaviour I encountered happens only on newer versions of iOS?

Sample project which reproduces the issue - note, it is intended to work only in landscape:

import UIKit

final class ViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
    
    private var pageController: UIPageViewController?
    private var pageControllerViewLeadingAnchor: NSLayoutConstraint?

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // init
        pageController = UIPageViewController(transitionStyle: .pageCurl, navigationOrientation: .horizontal, options: nil)
        pageController?.dataSource = self
        pageController?.delegate = self
        
        // adding it
        addChild(pageController!)
        view.addSubview(pageController!.view)
        
        // constraints
        pageController?.view.translatesAutoresizingMaskIntoConstraints = false
        pageController?.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        pageController?.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        pageControllerViewLeadingAnchor = pageController?.view.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: -view.bounds.width/4)
        pageControllerViewLeadingAnchor?.isActive = true
        pageController?.view.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    }
        
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
            
            // x translation animation
            UIView.animate(withDuration: 0.3, animations: {
                self.pageControllerViewLeadingAnchor?.constant = 0
                self.view.layoutIfNeeded()
            })
            
            // pageController curl animation
            let vc = UIViewController()
            let vc2 = UIViewController()
            vc.view.backgroundColor = .red
            vc2.view.backgroundColor = .blue
            self.pageController?.setViewControllers([vc, vc2], direction: .forward, animated: true, completion: nil)
        }
    }

    func pageViewController(_ pageViewController: UIPageViewController, spineLocationFor orientation: UIInterfaceOrientation) -> UIPageViewController.SpineLocation {
        
        // setting spine to mid and adding vcs
        let vc = UIViewController()
        let vc2 = UIViewController()
        vc2.view.backgroundColor = .green
        pageController?.setViewControllers([vc, vc2], direction: .forward, animated: true, completion: nil)
        pageController?.isDoubleSided = true
        return .mid
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        return UIViewController()
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        return UIViewController()
    }

}
UIPageViewController curl transition bug since iOS 16
 
 
Q