gpt4 book ai didi

SwiftUI:绑定(bind)从环境对象派生的结构的属性

转载 作者:行者123 更新时间:2023-12-03 08:10:26 26 4
gpt4 key购买 nike

我的任务管理器应用程序中有两个结构:

struct Task {
var identifier: String
var title: String
var tags: [String] // Array of tag identifiers
}
struct Tag {
var identifier: String
var title: String
}

然后我有一个类来存储它们:

class TaskStore: ObservableObject {
@Published var tasks = [String:Task]()
@Published var tags = [String:Tag]()
}

我将其作为 .environmentObject(taskStore) 传递到我的 Root View 。

如果以下任何错误,请纠正我(针对不良做法):

在我的 TaskView 中,我有:

    @EnvironmentObject var taskStore: TaskStore

var taskIdentifier: String // Passed from parent view

private var task: Task {
get {
return taskStore.tasks[taskIdentifier]! // Looks up the task in the store
}
}
private var tags: [Tag] {
get {
return taskStore.tags
}
}

问题是,在学习 SwiftUI 时,我被告知在制作某些组件时(例如在本例中允许您更改标签数组的选择器)它应该接受对值/集合的绑定(bind),或者说我想要制作任务标题可编辑,我需要绑定(bind)到 task.title 属性,这两个我都无法做到,因为(基于我定义和计算 task) 我无法绑定(bind)任务

我在这里做了一些违反最佳实践的事情吗?或者沿着这条路我在哪里偏离了在环境对象中存储事实点并使其在 subview 中可编辑的正确方法。

最佳答案

不,您不一定会做一些违反最佳实践的事情。我认为在 SwiftUI 中,数据模型存储和操作的概念很快就会变得比 Apple 在其演示代码中展示的内容更加复杂。对于一个真正的应用程序,具有单一的事实来源,就像您似乎正在使用的那样,您将必须想出一些方法将数据绑定(bind)到您的 View 。

一种解决方案是使用您自己的与 ObservableObject 交互的 getset 属性编写 Binding 。例如,这可能看起来像这样:

struct TaskView : View {
var taskIdentifier: String // Passed from parent view

@EnvironmentObject private var taskStore: TaskStore

private var taskBinding : Binding<Task> {
Binding {
taskStore.tasks[taskIdentifier] ?? .init(identifier: "", title: "", tags: [])
} set: {
taskStore.tasks[taskIdentifier] = $0
}
}

var body: some View {
TextField("Task title", text: taskBinding.title)
}
}

如果您不喜欢这种事情,避免这种情况的一种方法是使用 CoreData。因为模型被系统制作成 ObservableObject ,所以您通常可以避免这种事情并直接传递和操作您的模型。然而,这并不一定意味着它是正确(或更好)的选择。

您可能还想探索TCA这是一个越来越流行的状态管理和 View 绑定(bind)库,它为您正在做的事情类型提供了很多内置解决方案。

关于SwiftUI:绑定(bind)从环境对象派生的结构的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71002619/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com