【问题标题】:SwiftUI & Core Data - How do I use a parent record in a predicate?SwiftUI 和 Core Data - 如何在谓词中使用父记录?
【发布时间】:2020-02-26 20:01:18
【问题描述】:

是否可以在 SwiftUI 的 @FetchRequest 属性包装器内的谓词中使用核心数据记录?

我有一个项目列表和一个任务列表。我想点击一个项目并导航到该项目的相关任务列表。我似乎找不到以 SwiftUI 可以看到 @FetcheRequest 初始化之前看到的方式传入父项目。

我尝试将父项目放在 EnvironmentObject 中。当我从 ProjectListView 导航到 TaskListView 时调用它。

TaskListView()
   .environment(\.managedObjectContext, self.managedObjectContext)
   .environmentObject(self.projectToEdit)

然后在我添加的TaskListView中尝试了这个:

    @Environment(\.managedObjectContext) var managedObjectContext

    @EnvironmentObject var parentProject: Project

    @FetchRequest(
        entity: Task.entity(),
        sortDescriptors: [
            NSSortDescriptor(keyPath: \Task.name, ascending: true)
        ],
        predicate: NSPredicate(format: String(format: "%@%@", "taskProject", " == %@"), parentProject)
    ) var tasks: FetchedResults<Task>

我在谓词行收到以下错误。

不能在属性初始化器中使用实例成员“parentProject”;属性初始化器在“self”可用之前运行

那么有没有办法以某种方式编写可以使用父项目的谓词?将项目传递给任务视图似乎不会起作用。我还能如何在这样的谓词中使用记录?

【问题讨论】:

    标签: core-data swiftui


    【解决方案1】:

    FetchRequest 可以在init 方法中动态创建。这样你就可以改变谓词和排序条件。下面是一些示例代码来实现这一点。

    // sample Project class
    class Project:NSManagedObject {
        var id : String
        var name : String
    }
    
    // sample Task class
    class Task:NSManagedObject {
        var id : String
        var prjId : String
        var name : String
    }
    
    // Task List View
    struct TaskListView: View {
        @Environment(\.managedObjectContext) var managedObjectContext
    
        private var tasksRequest: FetchRequest<Task>
        private var tasks: FetchedResults<Task> { tasksRequest.wrappedValue }
    
        private var project:Project
    
        // init Task with Project
        init(_ project:Project) {
            self.project = project
    
            // create FetchRequest
            self.tasksRequest = FetchRequest(
                entity: Task.entity(),
                sortDescriptors: [NSSortDescriptor(key: "name", ascending:true)],
                predicate: NSPredicate(format: "prjId == %@", project.id))
        }
    
        var body: some View {
            VStack {
                Section(header: Text("Tasks under \(project.name):")) {
                    // access the fetched objects
                    ForEach(tasks, id:\.id) { task in
                        Text("\(task.name)")
                    }
                }
            }
        }
    }
    

    那么对TaskListView() 的调用将如下所示:

    // call to TaskListView
    TaskListView(self.projectToEdit)
        .environment(\.managedObjectContext, self.managedObjectContext)
    

    【讨论】:

    • 这比我使用的草率解决方法要好得多。我一直忘记可以在不初始化的情况下定义常量。
    猜你喜欢
    • 1970-01-01
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    • 2020-11-23
    • 2013-07-10
    • 2011-01-18
    • 2020-01-04
    相关资源
    最近更新 更多