使用 NSPredicate 根据数组属性过滤 CoreData 项列表
Posted
技术标签:
【中文标题】使用 NSPredicate 根据数组属性过滤 CoreData 项列表【英文标题】:Filter a list of CoreData items based on an array property using NSPredicate 【发布时间】: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 中的随意代码,我只是想了解我正在尝试做的事情。)
结果
就目前而言,这会在运行时崩溃。 任何帮助将不胜感激。
【问题讨论】:
【参考方案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
是一个计算属性。已修复并感谢您的捕获。以上是关于使用 NSPredicate 根据数组属性过滤 CoreData 项列表的主要内容,如果未能解决你的问题,请参考以下文章