Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

Crash/Glitch when using setViewControllers(_:animated:) with UIHostingController and .refreshable in SwiftUI

Introduction

Hello,

As part of our ongoing migration to SwiftUI, we are currently managing navigation using UIKit. Our SwiftUI views are embedded in UIHostingController instances and pushed or presented via UINavigationController.

We’ve encountered an issue that causes either a UI glitch on iOS 18 or a crash on iOS 17 when using the .refreshable modifier in a SwiftUI view that is added to a UINavigationController via setViewControllers(_:animated:).

To reproduce the issue, we’re using the following simple SwiftUI view:

struct TestView: View {
    var body: some View {
        List {
            ForEach(0...100, id: \.self) {
                Text("Number: \($0)")
            }
        }
        .refreshable {
            // No action needed — the presence of this modifier alone triggers the issue
        }
    }
}

Problematic Scenario

The following code causes the issue:

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        let initialNav = self.navigationController

        let hostingController = UIHostingController(rootView: TestView())
        let newNav = UINavigationController()

        // This causes a freeze (iOS 18) or crash (iOS 17)
        newNav.setViewControllers([hostingController], animated: true)

        initialNav?.present(newNav, animated: true)
    }
}

After presenting the navigation controller, our app is freezing on iOS 18 or crashing on iOS 17.

Working scenario

When using pushViewController(_:animated:), the issue does not occur:

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        let initialNav = self.navigationController

        let hostingController = UIHostingController(rootView: TestView())
        let newNav = UINavigationController()

        // This works without issue
        newNav.pushViewController(hostingController, animated: true)

        initialNav?.present(newNav, animated: true)
    }
}

Conclusion

We would like to better understand the root cause of this behavior. While using pushViewController is a viable workaround, there are scenarios where we must rely on setViewControllers, and currently, that approach breaks the experience or crashes the app.

Is this a known issue, or are we missing something about how UIHostingController interacts with .refreshable in this context?

Thanks for your time — we look forward to any insights you can share.

I've tested the code snippet you provided using iOS 18.4 and I'm unable to reproduce the issue. Do you get the same results with just the relevant code in a small test project? If so, please share a link to your test project. That'll help us better understand what's going on. If you're not familiar with preparing a test project, take a look at Creating a test project.

Hello @DTS Engineer,

Thank you for taking the time to evaluate this issue. I forgot to mention that the initial ViewController needs to be embedded in an UINavigationController in order to trigger the issue (otherwise the present method is never called).

We can update the code of the ViewController in the following way in order to remove this requirement and still trigger the issue:

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
  
        let hostingController = UIHostingController(rootView: TestView())
        let newNav = UINavigationController()
 
        // This causes a freeze (iOS 18) or crash (iOS 17)
        newNav.setViewControllers([hostingController], animated: true)
 
        present(newNav, animated: true)
    }
}

To simplify our further exchanges, I created a test project where you can reproduce the issue. You will find the project at this url.

Sorry for the inconvenience, let us know if you could reproduce it using our test project.

Thanks.

Crash/Glitch when using setViewControllers(_:animated:) with UIHostingController and .refreshable in SwiftUI
 
 
Q