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

SwiftUI中如何通过navigationDestination传递FocusState?

问题分析与解决方案

跨导航视图传递父视图的FocusState绑定无法正常关闭键盘,核心原因是**FocusState的作用域绑定到原视图的视图层级**,导航后的新视图属于独立的导航栈层级,导致状态变更无法正确同步到新视图的TextField。

以下是两种可行的解决方式:

方案1:让目标视图独立管理FocusState

这是最符合SwiftUI状态管理规范的做法,每个视图负责自身的焦点状态:

修改View_2代码,自行声明并管理FocusState:

struct View_2: View {
    @ObservedObject var viewModel: View_1.ViewModel
    @FocusState private var localFocus: View_1.ViewModel.Field? // 本地焦点状态

    var body: some View {
        VStack {
            TextField("", $viewModel.name)
                .focused($localFocus, equals: .myTextField) // 绑定本地状态
                .toolbar {
                    ToolbarItemGroup(placement: .keyboard) {
                        Button {
                            localFocus = nil // 直接关闭本地焦点
                        } label: {
                            Image(systemName: "keyboard")
                        }
                    }
                }
        }
        .onAppear {
            localFocus = .myTextField // 进入视图自动唤起键盘
        }
    }
}

View_1中无需传递FocusState绑定,直接初始化View_2即可:

.navigationDestination(for: MyViews) { navigation in
    if navigation == MyViews.secondView {
        View_2(viewModel: viewModel)
    }
}

方案2:通过ViewModel传递焦点控制信号

如果需要在父视图和子视图间同步焦点状态,可以在ViewModel中添加信号属性,触发焦点变更:

首先更新ViewModel:

extension View_1 {
    @MainActor
    class ViewModel: ObservableObject {
        @Published var name: String = ""
        @Published var shouldResignFocus = false // 新增焦点控制信号

        enum Field: Hashable {
            case myTextField
        }
    }
}

然后在View_2中监听信号,控制本地焦点:

struct View_2: View {
    @ObservedObject var viewModel: View_1.ViewModel
    @FocusState private var localFocus: View_1.ViewModel.Field?

    var body: some View {
        VStack {
            TextField("", $viewModel.name)
                .focused($localFocus, equals: .myTextField)
                .toolbar {
                    ToolbarItemGroup(placement: .keyboard) {
                        Button {
                            viewModel.shouldResignFocus = true // 触发关闭信号
                        } label: {
                            Image(systemName: "keyboard")
                        }
                    }
                }
        }
        .onAppear {
            localFocus = .myTextField
        }
        .onChange(of: viewModel.shouldResignFocus) { newValue in
            if newValue {
                localFocus = nil
                viewModel.shouldResignFocus = false // 重置信号
            }
        }
    }
}

这种方式下,父视图也可以通过修改viewModel.shouldResignFocus = true来远程关闭View_2的键盘。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 05:33:16