When a UIPageViewController is pushed in a UINavigationController, the leading swipe action from middle of screen dismisses the PageViewController instead of going to previous page.
When the Example code is opened from Xcode 16.4.0,
- ✅ Left Swipe action from left screen edge of screen dismisses the Page View Controller.
- ✅ Left Swipe action from middle of screen goes to previous Page in Page View Controller
When the Example code is opened from Xcode 26.0 - Beta 6,
- ✅ Left Swipe action from left screen edge of screen dismisses the Page View Controller.
- ❌ Left Swipe action from middle of screen sometimes goes to previous page and sometimes dismisses the Page View Controller.
Example code that the issue occurs:
import Foundation
import UIKit
import PlaygroundSupport
PlaygroundPage.current.setLiveView(
UINavigationController(rootViewController: RootViewController())
)
class RootViewController: UIViewController {
lazy var pageVCButton: UIButton = {
let button = UIButton()
button.setTitle("Open Page VC", for: .normal)
button.setTitleColor(.label, for: .normal)
button.addAction(UIAction(handler: { [weak self] _ in
self?.didTapPageVCButton()
}), for: .touchUpInside)
return button
}()
lazy var pageContainerViewController = PageContainerViewController(startIndex: 3)
func didTapPageVCButton() {
print("didTapPageVCButton")
navigationController?.pushViewController(pageContainerViewController, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
addOpenPageVCButton()
}
private func addOpenPageVCButton() {
view.addSubview(pageVCButton)
pageVCButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
pageVCButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
pageVCButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),
])
}
}
class PageContainerViewController: UIViewController {
lazy var pageViewController: UIPageViewController = {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal,
options: nil
)
pageViewController.dataSource = self
pageViewController.delegate = self
return pageViewController
}()
lazy var pages: [ColouredViewController] = [
ColouredViewController(backgroundColor: .red),
ColouredViewController(backgroundColor: .blue),
ColouredViewController(backgroundColor: .green),
ColouredViewController(backgroundColor: .yellow),
ColouredViewController(backgroundColor: .brown),
ColouredViewController(backgroundColor: .link),
ColouredViewController(backgroundColor: .cyan),
]
var startIndex = 0
init(startIndex: Int) {
super.init(nibName: nil, bundle: nil)
self.startIndex = startIndex
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.title = "Page View Controller"
print(pageViewController.gestureRecognizers)
setupPageViewController()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
private func setupPageViewController() {
addChild(pageViewController)
view.addSubview(pageViewController.view)
pageViewController.didMove(toParent: self)
pageViewController.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
pageViewController.view.topAnchor.constraint(equalTo: view.topAnchor),
pageViewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
pageViewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
pageViewController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
])
pageViewController.setViewControllers([pages[startIndex]], direction: .forward, animated: true)
}
}
extension PageContainerViewController: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
print("Leading Swipe")
guard let viewController = viewController as? ColouredViewController else { return nil }
guard let currentPageIndex = pages.firstIndex(of: viewController) else { return nil }
if currentPageIndex == 0 { return nil }
return pages[currentPageIndex - 1]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
print("Trailing Swipe")
guard let viewController = viewController as? ColouredViewController else { return nil }
guard let currentPageIndex = pages.firstIndex(of: viewController) else { return nil }
if currentPageIndex == pages.count - 1 { return nil }
return pages[currentPageIndex + 1]
}
}
extension PageContainerViewController: UIPageViewControllerDelegate {}
class ColouredViewController: UIViewController {
var backgroundColor: UIColor?
init(backgroundColor: UIColor) {
super.init(nibName: nil, bundle: nil)
self.backgroundColor = backgroundColor
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = backgroundColor
}
}