【问题标题】:Filter a list of CoreData items based on an array property using NSPredicate使用 NSPredicate 根据数组属性过滤 CoreData 项列表
【发布时间】:2020-05-19 12:12:05
【问题描述】:

上下文

我有一个名为“任务”的核心数据实体

“任务”与另一个名为“标签”的实体有关系:@NSManaged public var tags: NSSet? 此数据存储为:

public var tagsArray: [Tag] {
    let set = tags as? Set<Tag> ?? []

    return set.sorted {
        $0.wrappedTagTitle < $1.wrappedTagTitle
    }
}

如果任务列表包含某个标签,即标题为“学校”,我正在尝试过滤它们。

var fetchRequest: FetchRequest<Task>

init(tagFilterName: String) {
    let tag = Tag()
    tag.title = tagFilterName
    fetchRequest = FetchRequest<Task>(entity: Task.entity(), sortDescriptors: [], predicate: NSPredicate(format: "tagsArray CONTAINS %@", tag))
}

这是在父视图中初始化的:

FilteredScrollView(tagFilterName: "School")

(请原谅 init 中的随意代码,我只是想了解我正在尝试做的事情。)

结果

就目前而言,这会在运行时崩溃。 任何帮助将不胜感激。

【问题讨论】:

    标签: core-data swiftui nspredicate


    【解决方案1】:

    直接的问题是您调用Tag() 来创建一个新实例,该实例不调用指定的初始化程序。要创建一个新的Tag,您需要使用Tag(context: NSManagedObjectContext)。您遇到崩溃是因为您尝试使用未正确初始化的对象。

    不过,这只是问题的一部分。如果你修复它,你将修复崩溃,但你会得到零结果。另一个问题是您不应该为获取创建新的Tag。 Core Data 谓词寻找完全匹配——没有像Equatable 这样的东西,它不会寻找具有相同标题的其他Tag。它会寻找那个确切的标签。但是由于您刚刚创建了该标签,并且由于它未连接到任何任务,因此您将获得零结果。 CONTAINS 运算符不会匹配任何内容,因为没有 Task 包含您刚刚创建的 Tag

    要通过关系匹配属性值——在这种情况下,通过tags 关系匹配Tag.title——你的谓词看起来像

    NSPredicate(format: "any tags.title = %@", tagFilterName)
    

    在获取Task 时,这会要求任何Task,其中tags 关系的任何成员的值等于tagFilterName

    【讨论】:

    • 除了上面 Tom 的观点,请注意(对于 SQLite 存储)CoreData 在执行提取时将无法识别计算属性 tagsArray。但是您可以使用底层关系tags,而不是:即。 “任何标签。标题 == %@”。
    • 哎呀,我忘了tagsArray 是一个计算属性。已修复并感谢您的捕获。
    猜你喜欢
    • 1970-01-01
    • 2017-09-20
    • 1970-01-01
    • 2015-01-23
    • 2015-07-02
    • 2015-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多