It seems UINavigationControllers do not play nicely with UIHostingController.
When presenting a UIHostingController, the UINavigationBar does not update with the nav bar title until after the SwiftUI view has finished appearing on screen.
This only happens the first time the hosting controller loads its view. If you were to store the hosting controller somewhere, then try to present it a second time, everything works as expected.
Feedback: FB13287789
Pretty easy to reproduce:
Scene Delegate:
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
let navigationController = UINavigationController()
let contentView = RootView(navController: navigationController) { navController in
navController.pushViewController(UIHostingController(rootView: SearchView()), animated: true)
}
let firstController = UIHostingController(rootView: contentView)
navigationController.setViewControllers([firstController], animated: false)
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
}
func sceneDidDisconnect(_ scene: UIScene) {}
func sceneDidBecomeActive(_ scene: UIScene) {}
func sceneWillResignActive(_ scene: UIScene) {}
func sceneWillEnterForeground(_ scene: UIScene) {}
func sceneDidEnterBackground(_ scene: UIScene) {}
}
SwiftUI Views:
import UIKit
import SwiftUI
struct RootView: View {
var navController: UINavigationController
var didTapButton: (UINavigationController) -> ()
var body: some View {
Button {
didTapButton(navController)
} label: {
Text("Tap this to show broken search bar animation")
}
.navigationTitle("First Page")
.navigationBarTitleDisplayMode(.inline)
}
}
struct SearchView: View {
let items: [Int] = {
(0...100).map {$0}
}()
@State var searchText: String = ""
var body: some View {
List {
ForEach(items, id: \.self) { item in
Text("\(item)")
}
}
.listStyle(.plain)
.navigationTitle("Search Page")
.navigationBarTitleDisplayMode(.inline)
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always), prompt: "Search")
}
}