Передача отношений CoreData по иерархии представления - PullRequest
0 голосов
/ 14 апреля 2020

Я очень стараюсь передать объекты CoreData с сильными отношениями one2many по моему мнению Heirarchy.

Представьте себе приложение Todolist:

  1. Каждый объект List имеет отношение one2many с объектом Task.

  2. Каждый объект Task имеет отношение one2many с объектом SubTask.

Я запрашиваю CoreData в root с FetchedRequests для получения объекта List. Теперь я перебираю объекты Task и создаю View для каждого из них. Затем в каждом из этих представлений мне нужно перебирать его объекты подзадачи. На каждом из этих уровней можно вносить изменения и распространять их обратно.

Мне действительно тяжело с таким кодом:

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)
            }
        }
    }
}

Это дает много ошибок. Например:

  1. Если я изменю его на использование индикаторов, он говорит, что не имеет атрибута .indicies

  2. Прямо сейчас он говорит Generi c struct «ForEach» требует, чтобы «NSOrderedSet» соответствовал «RandomAccessCollection»

  3. Значение типа «NSOrderedSet.Element» (иначе «Any») не имеет члена «id»

И много других на счет.

У вас есть лучший метод? Должен ли я делать запросы из coredata на каждом шагу? Я действительно не знаю, почему так сложно перенести то, что у меня уже было, с Bindings и структурой данных уровня root на coredata.

Кажется, я не могу запросить только один элемент из базы данных по UUID. Я sh это было больше похоже на mongodb, чем sql.

Вот пример проекта, который я сделал, чтобы упростить задачу. Интересно, может ли кто-нибудь взглянуть?

https://github.com/ryanpeach/MySwiftTaskList

Это основные виды:

TaskList + Extensions

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
    }
}

ContentView (root)

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)
        }
    }
}

TaskListView

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. У меня были примеры, работающие из статического c источника данных вроде json, и он работал безупречно, так что, я думаю, я просто не понимаю ограничений этого типа данных.

1 Ответ

0 голосов
/ 16 апреля 2020

Пользователь на Discord сказал мне, что я должен использовать @ObservedObject вместо @Binding для объектов CoreData, и это работает фантастически c. Это было действительно так просто.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...