【发布时间】:2020-07-27 16:48:27
【问题描述】:
我正在努力将具有强 one2many 关系的 CoreData 对象传递到我的视图层次结构中。
想象一下 Todolist 应用:
每个 List 对象都与 Task 对象存在一对多关系。
每个 Task 对象都与 SubTask 对象存在一对多关系。
我使用 FetchedRequests 在根处查询 CoreData 以获取 List 对象。我现在遍历任务对象,并为每个对象创建一个视图。然后在每个视图中,我需要遍历它的 SubTask 对象。在这些级别中的每一个,都可以进行编辑,并且应该进行备份。
我很难处理这样的代码:
struct TaskListView: View {
@Environment(\.managedObjectContext) var managedObjectContext
@Binding var taskData: TaskData
var body: some View {
List{
ForEach(self.taskList.tasks ?? [], id: \.id) { t in
TaskRowView(taskData: $t)
}
}
}
}
这会产生很多错误。喜欢:
如果我将其更改为使用索引,它会显示没有属性 .indicies
现在它说通用结构“ForEach”要求“NSOrderedSet”符合“RandomAccessCollection”
“NSOrderedSet.Element”(又名“Any”)类型的值没有成员“id”
还有很多其他的。
你有更好的方法吗?我应该在每一步都从 coredata 进行查询吗?我真的不知道为什么将我已经使用的 Bindings 和根级数据结构迁移到 coredata 如此困难。
我似乎无法通过 UUID 从数据库中仅查询一项。我希望这更像是 mongodb 而不是 sql。
这是我为简化问题而制作的示例项目。不知道有没有人可以看看?
https://github.com/ryanpeach/MySwiftTaskList
这些是主要视图:
任务列表+扩展
extension TaskList: Identifiable {
var duration: Double {
var out = 0.0
for t in self.tasks ?? [] {
out += (t as! Task).duration
}
return out
}
func getTasks() -> [Task] {
var out: [Task] = []
for t in self.tasks ?? [] {
out.append(t as! Task)
}
return out
}
}
内容视图(根)
import SwiftUI
import CoreData
struct ContentView: View {
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(
entity: TaskList.entity(),
sortDescriptors: [
NSSortDescriptor(
keyPath: \TaskList.name,
ascending: true
)
]) var taskListList: FetchedResults<TaskList>
@State private var taskListName: String = ""
var body: some View {
NavigationView {
VStack {
HStack{
TextField("TaskList Name", text: $taskListName)
Button(action: {
self.addTaskList()
}){
Text("Create Task List")
}
}
List{
ForEach(self.taskListList, id: \.name) { tl in
NavigationLink(destination: TaskListView(taskList: tl)) {
Text(tl.name)
Text(String(tl.duration))
}
}
}
}
}
}
func addTaskList() {
let newTask = TaskList(context: managedObjectContext)
// newTask.id = UUID()
newTask.name = taskListName
do {
try managedObjectContext.save()
} catch {
print(error)
}
}
}
任务列表视图
import SwiftUI
import CoreData
struct TaskListView: View {
@Environment(\.managedObjectContext) var managedObjectContext
@State private var taskName: String = ""
/* Option1: Does not work
var fetchRequest: FetchRequest<Task>
var tasks: FetchedResults<Task>
@State private var _taskList: TaskList?
init(taskList: TaskList) {
fetchRequest = FetchRequest<Task>(
entity: Task.entity(),
sortDescriptors: [
NSSortDescriptor(
keyPath: \Task.order,
ascending: true
)
],
predicate: NSPredicate(format: "taskList = %@", taskList)
)
_taskList = taskList
tasks = fetchRequest.wrappedValue
}
*/
@Binding var taskList: TaskList
var body: some View {
VStack {
HStack{
TextField("Task Name", text: $taskName)
Button(action: {
self.addTask()
}){
Text("Create Task")
}
}
List{
ForEach(self.taskList.getTasks(), id: \.order) { <------- The errors happen here
t in
HStack{
Text(t.name)
Text(String(t.duration))
}
}
}
}
}
func addTask() {
let newTask = Task(context: managedObjectContext)
// newTask.id = UUID()
newTask.name = taskName
taskList.addToTasks(newTask)
do {
try managedObjectContext.save()
} catch {
print(error)
}
}
}
struct TaskListView_Previewer: View {
@State var taskList: TaskList
var body: some View {
TaskListView(
taskList: $taskList
)
}
}
我真的很感激能从这一切中获得学习经验。只是不太确定我“应该”如何使用 CoreData 处理我的数据。我有一些从类似于 json 的静态数据源工作的示例,并且它完美地工作,所以我想我只是不了解这种数据类型的限制。
【问题讨论】: