Binding’s inside NavigationSplitView detail (TextField, TextEditor)

huangapple go评论64阅读模式
英文:

Binding’s inside NavigationSplitView detail (TextField, TextEditor)

问题

以下是您提供的代码的翻译部分:

我正在使用一个两列的`NavigationSplitView`。尝试找出如何通过`.onSubmit`修饰符来更新数据模型并使用`TextField`视图而不使用`Binding.constant`

`detail`部分中,我有`TextField``TextEditor`

1. 如何避免使用`Binding.constant()`?我的意思是,我需要进行突变。
2. 更新Model中的`value`属性的正确方法是什么?

我需要在列表中进行单一选择。

这是我的示例代码(70行):

```swift
struct Model: Identifiable, Hashable {
    var id = UUID()
    var title: String = "全新的品牌"
    var value: String = ""
    
    func updateValue() async -> Model {
        return Model(id: id, title: title, value: "野猪🐷正在快乐地奔跑在田野中")
    }
}

final class DataModel: ObservableObject {
    @Published
    var models: [Model] = [
        .init(title: "第一个", value: "毛皮"),
        .init(title: "第二个", value: "喵喵"),
        .init(title: "另一个", value: "创造SwiftUI,不是战争")
    ]
    
    @MainActor
    func updateModel(for model: Model.ID) async -> Void {
        var findModel = models.first { $0.id == model }
        findModel = await findModel?.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 }
        return 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 {
                VStack {
                    TextField("标题", text: .constant(selectedModel.title))
                        .padding()
                        .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 20))
                        .submitLabel(.go)
                        .onSubmit {
                            Task {
                                // 通过点击“Go”按钮更新Model.value
                                await dataModel.updateModel(for: selectedModel.id)
                            }
                        }
                    TextEditor(text: .constant(selectedModel.value))
                }
                .padding()
                .navigationTitle(selectedModel.title)
            }
        }
    }
}

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

请注意,代码中的引号已被翻译为中文,同时特殊字符如表情符号已保留在原文中。

英文:

I'm using a two-column NavigationSplitView. Trying to figure out how to update the data model via .onSubmit modifier and use a TextField view without Binding.constant.

Within the detail section, I have TextField and TextEditor.

  1. How to avoid Binding.contant()? I mean, I need mutation.
  2. This is a correct way to update value property in Model?

I need a single selection in List.

Here's my sample code (70 line’s):

struct Model: Identifiable, Hashable {
    var id = UUID()
    var title: String = "Brand new"
    var value: String = ""
    
    func updateValue() async -> Model {
        return 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 model: Model.ID) async -> Void {
        var findModel = models.first { $0.id == model }
        findModel = await findModel?.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 }
        return 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 {
                VStack {
                    TextField("Title", text: .constant(selectedModel.title))
                        .padding()
                        .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 20))
                        .submitLabel(.go)
                        .onSubmit {
                            Task {
                                // Update Model.value by hit `Go`
                                await dataModel.updateModel(for: selectedModel.id)
                            }
                        }
                    TextEditor(text: .constant(selectedModel.value))
                }
                .padding()
                .navigationTitle(selectedModel.title)
            }
        }
    }
}

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

答案1

得分: 1

以下是代码部分的中文翻译:

struct Model: Identifiable, Hashable {
    var id = UUID()
    var title: String = "全新"
    var value: String = ""
    
    func updateValue() async -> Model {
        return Model(id: id, title: title, value: "野猪 🐷 正在快乐地奔跑在田野上")
    }
}

final class DataModel: ObservableObject {
    @Published
    var models: [Model] = [
        .init(title: "第一个", value: "毛皮"),
        .init(title: "第二个", value: "喵喵"),
        .init(title: "另一个", value: "创造 SwiftUI,而不是战争")
    ]
    
    @MainActor
    func updateModel(for model: Binding<Model>) async -> Void {
        model.wrappedValue = await model.wrappedValue.updateValue()
    }
    
    func bindingToModel(_ model: Model.ID) -> Binding<Model> {
        Binding<Model> {
            guard let index = self.models.firstIndex(where: { $0.id == model }) else {
                return Model()
            }
            return self.models[index]
        } set: { newModel in
            guard let index = self.models.firstIndex(where: { $0.id == model }) else { return }
            self.models[index] = newModel
        }
    }
}

struct ModelView: View {
    @StateObject
    private var dataModel = DataModel()
    
    @State
    private var listSelection: Model.ID?
    
    var body: some View {
        NavigationSplitView {
            List(dataModel.models, selection: $listSelection) { model in
                NavigationLink(model.title, value: model.id)
            }
        } detail: {
            if let listSelection, let bindModel = dataModel.bindingToModel(listSelection)  {
                VStack {
                    TextField("标题", text: bindModel.title)
                        .padding()
                        .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 20))
                        .submitLabel(.go)
                        .onSubmit {
                            Task {
                                // 通过点击“Go”按钮更新 Model.value
                                await dataModel.updateModel(for: bindModel)
                            }
                        }
                    TextEditor(text: bindModel.value)
                }
                .padding()
                .navigationTitle(bindModel.title)
            }
        }
    }
}

请注意,我已经将代码中的英文文本翻译成了中文。

英文:

After a couple of days, I realized what I could do.
No one answered the question, so I solved the problem this way.

The final solution is below:

struct Model: Identifiable, Hashable {
    var id = UUID()
    var title: String = &quot;Brand new&quot;
    var value: String = &quot;&quot;
    
    func updateValue() async -&gt; Model {
        return Model(id: id, title: title, value: &quot;The boar &#128023; is running through the field happily&quot;)
    }
}

final class DataModel: ObservableObject {
    @Published
    var models: [Model] = [
        .init(title: &quot;First&quot;, value: &quot;fur&quot;),
        .init(title: &quot;Second&quot;, value: &quot;meow&quot;),
        .init(title: &quot;Another&quot;, value: &quot;Make SwiftUI, not war&quot;)
    ]
    
    @MainActor
    func updateModel(for model: Binding&lt;Model&gt;) async -&gt; Void {
        model.wrappedValue = await model.wrappedValue.updateValue()
    }
    
    func bindingToModel(_ model: Model.ID) -&gt; Binding&lt;Model&gt; {
        Binding&lt;Model&gt; {
            guard let index = self.models.firstIndex(where: { $0.id == model }) else {
                return Model()
            }
            return self.models[index]
        } set: { newModel in
            guard let index = self.models.firstIndex(where: { $0.id == model }) else { return }
            self.models[index] = newModel
        }
    }
}

struct ModelView: View {
    @StateObject
    private var dataModel = DataModel()
    
    @State
    private var listSelection: Model.ID?
    
    var body: some View {
        NavigationSplitView {
            List(dataModel.models, selection: $listSelection) { model in
                NavigationLink(model.title, value: model.id)
            }
        } detail: {
            if let listSelection, let bindModel = dataModel.bindingToModel(listSelection)  {
                VStack {
                    TextField(&quot;Title&quot;, text: bindModel.title)
                        .padding()
                        .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 20))
                        .submitLabel(.go)
                        .onSubmit {
                            Task {
                                // Update Model.value by hit `Go`
                                await dataModel.updateModel(for: bindModel)
                            }
                        }
                    TextEditor(text: bindModel.value)
                }
                .padding()
                .navigationTitle(bindModel.title)
            }
        }
    }
}

huangapple
  • 本文由 发表于 2023年2月19日 02:23:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75495453.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定