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

NavigationSplitView详情页TextField/TextEditor绑定与模型更新问题

问题解决:NavigationSplitView 数据绑定与模型更新

1. 避免使用Binding.constant(),实现双向数据绑定

Binding.constant()会让输入控件变为只读状态,要实现可编辑功能,需在详情视图中创建临时状态变量绑定输入控件,提交时同步到数据模型:

  • 在详情区域的VStack内部,声明@State变量存储编辑中的标题和内容
  • 将TextField和TextEditor绑定到这些临时变量
  • 在.onSubmit回调中调用模型更新方法,把临时变量的值同步回数据源

2. 修正Model.value的更新逻辑

当前updateModel方法仅修改了局部变量,未更新dataModel.models数组中的元素,需找到目标模型的索引并替换:

  • 在DataModel的updateModel方法中,先定位目标模型在数组中的索引
  • 调用更新方法获取新模型,替换数组对应位置的元素
  • 若需支持自定义输入内容更新,可修改updateValue方法接收参数,直接使用临时变量的值更新

3. 实现列表单选功能

当前代码的List(selection: $listSelection)已支持单选,只需确保:

  • listSelection声明为@State private var listSelection: Model.ID?(可选类型默认支持单选)
  • NavigationLink的value绑定到model.id,与List的selection类型匹配

修改后的完整代码

struct Model: Identifiable, Hashable {
    var id = UUID()
    var title: String = "Brand new"
    var value: String = ""
    
    // 支持自定义内容更新的方法
    func updateValue(with newValue: String) -> Model {
        Model(id: id, title: title, value: newValue)
    }
    
    // 保留原有示例的固定更新逻辑(可选)
    func updateValue() -> Model {
        Model(id: id, title: title, value: "The boar 🐗 is running through the field happily")
    }
}

final class DataModel: ObservableObject {
    @Published
    var models: [Model] = [
        .init(title: "First", value: "fur"),
        .init(title: "Second", value: "meow"),
        .init(title: "Another", value: "Make SwiftUI, not war")
    ]
    
    @MainActor
    func updateModel(for modelId: Model.ID, withTitle newTitle: String, newValue: String) {
        guard let index = models.firstIndex(where: { $0.id == modelId }) else { return }
        models[index] = models[index].updateValue(with: newValue)
        models[index].title = newTitle
    }
    
    // 保留原有示例的固定更新方法(可选)
    @MainActor
    func updateModel(for modelId: Model.ID) {
        guard let index = models.firstIndex(where: { $0.id == modelId }) else { return }
        models[index] = models[index].updateValue()
    }
}

struct ModelView: View {
    @StateObject
    private var dataModel = DataModel()
    
    @State
    private var listSelection: Model.ID?
    
    private var selectedModel: Model? {
        guard let selection = listSelection else { return nil }
        dataModel.models.first { $0.id == selection }
    }
    
    var body: some View {
        NavigationSplitView {
            List(dataModel.models, selection: $listSelection) { model in
                NavigationLink(model.title, value: model.id)
            }
        } detail: {
            if let selectedModel {
                @State var editedTitle = selectedModel.title
                @State var editedValue = selectedModel.value
                
                VStack {
                    TextField("Title", text: $editedTitle)
                        .padding()
                        .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 20))
                        .submitLabel(.go)
                        .onSubmit {
                            dataModel.updateModel(for: selectedModel.id, withTitle: editedTitle, newValue: editedValue)
                        }
                    TextEditor(text: $editedValue)
                        .padding()
                        .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 20))
                }
                .padding()
                .navigationTitle(selectedModel.title)
                .onChange(of: selectedModel) { newModel in
                    editedTitle = newModel?.title ?? ""
                    editedValue = newModel?.value ?? ""
                }
            } else {
                Text("请选择一个项目")
                    .navigationTitle("无选择")
            }
        }
    }
}

struct ModelView_Previews: PreviewProvider {
    static var previews: some View {
        ModelView()
            .colorScheme(.light)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:02:57