iOS 18 Beta中SwiftUI导航栏UISearchBar不显示问题求助
iOS 18 Beta 中导航栏UISearchBar不显示的解决思路
问题背景
在iOS 17及更早版本正常运行的代码,到iOS 18 Beta中出现导航栏.principal位置的UISearchBar(通过UIViewRepresentable封装)无法显示的问题,添加额外ToolbarItem能临时显示,但返回后又消失。这是iOS 18对Toolbar布局逻辑和UIKit视图兼容性调整导致的。
解决方法
方案1:改用SwiftUI原生组件替代UIKit封装
优先用SwiftUI原生组件实现搜索栏,彻底规避UIKit与SwiftUI的兼容性问题,在iOS18上表现稳定:
struct NextView: View { var number: Int @State private var text = "" @FocusState private var isSearchFocused: Bool var body: some View { Text("\(number)") .toolbar { ToolbarItem(placement: .principal) { // 模拟UISearchBar样式的原生TextField HStack(spacing: 8) { Image(systemName: "magnifyingglass") .foregroundColor(.secondary) TextField("Search", text: $text) .focused($isSearchFocused) .textFieldStyle(.plain) } .padding(.horizontal, 12) .padding(.vertical, 6) .background(Color(.systemGray5)) .cornerRadius(8) } // 可选:添加取消按钮,和原生搜索栏行为一致 ToolbarItem(placement: .topBarTrailing) { if isSearchFocused { Button("Cancel") { isSearchFocused = false text = "" } } } } .onAppear { // 可选:页面出现时自动聚焦搜索框 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { isSearchFocused = true } } } }
方案2:修复UIViewRepresentable的实现错误
原代码中直接在struct里声明let searchBar = UISearchBar()是值类型的错误用法,会导致实例复用异常,修改成在makeUIView内创建实例,并完善updateUIView逻辑:
struct SearchBar: UIViewRepresentable { @Binding var searchText: String var onSubmit: (() -> Void)? func makeUIView(context: Context) -> UISearchBar { let searchBar = UISearchBar() // 在这里创建实例,避免值类型复用问题 searchBar.placeholder = "Search" searchBar.text = searchText searchBar.delegate = context.coordinator return searchBar } func updateUIView(_ uiView: UISearchBar, context: Context) { // 同步文本变化,之前的updateUIView是空的,补上这个逻辑 if uiView.text != searchText { uiView.text = searchText } } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, UISearchBarDelegate { let parent: SearchBar init(_ parent: SearchBar) { self.parent = parent } func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { parent.searchText = searchText } func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { searchBar.resignFirstResponder() parent.onSubmit?() } } }
修改后NextView的Toolbar代码保持原样即可,iOS18下能正常显示且返回后不会消失。
方案3:强制Toolbar重新渲染(临时 workaround)
如果不想修改组件实现,可以通过重置Toolbar的id强制刷新,解决返回后消失的问题:
struct NextView: View { var number: Int @State private var text = "" @State private var toolbarId = UUID() var body: some View { Text("\(number)") .toolbar(id: toolbarId) { ToolbarItem(placement: .principal) { SearchBar(searchText: $text) } } .onAppear { // 页面出现时重置id,强制Toolbar重新加载 toolbarId = UUID() } } }
这个方法属于临时 workaround,适合快速验证,但推荐优先用前两个方案。
内容的提问来源于stack exchange,提问作者Toru
相关产品推荐
相关产品推荐

