preferredTransition not working when using setViewControllers(_:animated:)

I’m using the new preferredTransition = .zoom(...) API introduced in iOS 18.

Here’s a simplified version of what I do on app startup:

let listVC = CollectionViewController(collectionViewLayout: layout)
let detailVC = DetailViewController()
detailVC.preferredTransition = .zoom(sourceViewProvider: { context in
    let indexPath = IndexPath(row: 0, section: 0)
    let cell = listVC.collectionView.cellForItem(at: indexPath)
    return cell
})
let nav = UINavigationController()
nav.setViewControllers([listVC, detailVC], animated: false)
window?.rootViewController = nav
window?.makeKeyAndVisible()

This is meant to restore the UI state from a previous session — the app should launch directly into the DetailViewController.

The Problem

When I launch the app with setViewControllers([listVC, detailVC], animated: false), the transition from listVC to detailVC appears correctly (i.e., no animation, as intended), but the drag-to-dismiss gesture does not work. The back button appears, and tapping it correctly triggers the zoom-out transition back to the cell, so the preferredTransition = .zoom(...) itself is properly configured.

Interestingly, if I delay the push with a DispatchQueue.main.async and instead do:

nav.setViewControllers([listVC], animated: false)
DispatchQueue.main.async {
    nav.pushViewController(detailVC, animated: true)
}

…then everything works perfectly — including the interactive swipe-to-dismiss gesture — but that introduces an unwanted visual artifact: the user briefly sees the listVC, and then it pushes to detailVC, which I’m trying to avoid.

My Question

Is there a way to enable the swipe-to-dismiss gesture when using setViewControllers([listVC, detailVC], animated: false)

It can be very confusing for users if swipe-to-dismiss only works in certain cases inconsistently.

Thanks

@chou_ios are you trying to implement a Split View with a sidebar and detail view?

@DTS Engineer

I'm not building split view, nor am I using UISplitViewController — my view hierarchy is quite simple.

I have a standard UICollectionView, and tapping a cell is supposed to show a detail view. This is conceptually similar to the Apple sample code, where a detail view controller is pushed using navigationController.pushViewController.

However, due to the existing product behavior, I need to present the detail screen using: navigationController.setViewControllers([listViewController, detailViewController])

The issue is: I would still like to implement the fluid zoom transition effect as demonstrated in the Apple documentation, but it seems the transition isn't applied when using setViewControllers API

preferredTransition not working when using setViewControllers(_:animated:)
 
 
Q