You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中searchable导致返回后UI冻结问题求助

搜索框聚焦返回后UI冻结问题

问题复现代码

enum ViewRouter: Hashable, Codable {
    case pageOne
}

struct ContentView: View {
    
    @State var navStackPath = NavigationPath()
    
    var body: some View {
        
        NavigationStack(path: $navStackPath) {
            ZStack {
                Button {
                    navStackPath.append(ViewRouter.pageOne)
                } label: {
                    Text("SHOW DETAILS")
                }

            }
            .navigationDestination(for: ViewRouter.self) { d in
                switch d {
                case .pageOne:
                    DetailsView()
                }
            }
        }
    }
}

#Preview {
    ContentView()
}

struct DetailsView: View {
    
    @State var searchString = ""
    
    var body: some View {
        
        ZStack {
            Text("DETAILS")
        }
        .searchable(text: $searchString)
    }
}

问题演示

问题演示

问题现象

  • 点击SHOW DETAILS按钮
  • 进入详情页
  • 点击搜索框唤起键盘
  • 返回ContentView
  • 尝试点击SHOW DETAILS按钮,UI冻结,按钮完全失效

环境信息

  • Xcode版本:15.0 beta (15A5160n)、15.0 beta 2 (15A5161b)
  • 模拟器/真机:iPad模拟器(Version 15.0 (1004),SimulatorKit 633,CoreSimulator 905.2),真机也存在该问题

日志信息

UINavigationBar has changed horizontal size class without updating search bar to new placement. Fixing, but delegate searchBarPlacement callbacks have been skipped. navigationBar = <SwiftUI.UIKitNavigationBar: 0x10ad0c110; baseClass = UINavigationBar; frame = (1366 24; 1366 50); opaque = NO; autoresize = W; gestureRecognizers = <NSArray: 0x600000c717d0>; layer = <CALayer: 0x600000269d20>> delegate=0x111010000

解决方案

这是Xcode 15 beta版本中的SwiftUI已知bug,可通过以下方法规避:

方法1:用@FocusState管理搜索框焦点,页面消失时主动放弃焦点

修改DetailsView,添加焦点状态变量,在页面消失时重置焦点状态:

struct DetailsView: View {
    
    @State var searchString = ""
    @FocusState private var isSearchFocused: Bool
    
    var body: some View {
        
        ZStack {
            Text("DETAILS")
        }
        .searchable(text: $searchString)
        .focused($isSearchFocused)
        .onDisappear {
            isSearchFocused = false
        }
    }
}

方法2:通过UIKit强制取消键盘焦点

若方法1无效,可创建UIViewRepresentable组件强制放弃第一响应者:

struct DismissKeyboardHelper: UIViewRepresentable {
    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        view.backgroundColor = .clear
        return view
    }
    
    func updateUIView(_ uiView: UIView, context: Context) {
        uiView.endEditing(true)
    }
}

// 在DetailsView中调用
struct DetailsView: View {
    
    @State var searchString = ""
    
    var body: some View {
        
        ZStack {
            Text("DETAILS")
        }
        .searchable(text: $searchString)
        .onDisappear {
            _ = DismissKeyboardHelper()
        }
    }
}

方法3:临时回退到NavigationView

若上述方法仍无效,可暂时使用旧版NavigationView替代NavigationStack(需注意iOS版本兼容性),该bug在旧导航组件中未出现:

struct ContentView: View {
    var body: some View {
        NavigationView {
            ZStack {
                NavigationLink("SHOW DETAILS", destination: DetailsView())
            }
        }
    }
}

优先推荐方法1,代码简洁且符合SwiftUI状态管理逻辑。待Xcode正式版发布后,该bug大概率会被官方修复。

内容的提问来源于stack exchange,提问作者zumzum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 08:47:48