使用基于属性的过滤子元素集获取核心数据实体

Posted

技术标签:

【中文标题】使用基于属性的过滤子元素集获取核心数据实体【英文标题】:Fetch Core Data entity with a filtered set of child elements based on a property 【发布时间】:2014-12-30 22:20:58 【问题描述】:

我正在使用 CoreData 开发我的第一个应用程序,但我正在努力解决我认为的一个常见问题。

假设我有一个实体播放列表,它与另一个实体歌曲和视频具有 多对多 关系。所以我的播放列表对象看起来像这样

class Playlist : NSManagedObject 
    var songs: NSSet
    var videos: NSSet

Song 和 Video 实体都有一个“已删除”布尔字段,我使用它来跟踪已从播放列表中删除的歌曲或视频。我稍后调用我的远程 API 以在服务器端将其删除,但这是出于离线目的。

我想要的是从 CoreData 检索一个播放列表对象,其中包含未删除的歌曲和视频列表(因此那些删除 = false)。

我看到的一个解决方案是通过简单地获取实体播放列表来获取所有元素,然后手动过滤掉,但我想知道我是否可以使用 Core Data 更优雅地做到这一点。

【问题讨论】:

您可以只使用NSPredicate 来过滤播放列表的songsvideos 属性。或者,您可以使用 NSFetchRequest 来获取带有谓词的 Song 和 Videos 实体,即它们的 playlist 属性与您的播放列表匹配,并且 removed 属性是 false。无论哪种方式,您都需要分别制作歌曲和视频。 【参考方案1】:

欢迎来到核心数据。其工作方式如下:

首先获取播放列表。无论是否删除,它们与歌曲都有一对多的关系。 removed 属性不在 Playlist 实体中,因此在获取播放列表时无关紧要。

然后通过应用谓词获取 filtered 属性集:

let validSongs = aPlaylist.songs.filteredSetUsingPredicate(
   NSPredicate(format: "removed = false")
) 

换句话说,您不必担心 Core Data 正在从您的播放列表中检索哪些歌曲。底层有很多优化,所以 Core Data 很可能会使用一种称为“故障”的机制来检索它需要的数据。你还有别的注意事项要做!

IMO,这也是最“优雅”的解决方案。为了更简洁,您可以向您的 Playlist 实体添加一个检索有效歌曲的方法。

func validSongs() -> NSSet 
   if !self.songs.count   return NSSet()  
   return self.songs.filteredSetUsingPredicate(
      NSPredicate(format: "removed = false")
   ) 

然后使用

访问有效歌曲
aPlaylist.validSongs

【讨论】:

像魅力一样工作。谢谢你的解释,我现在很清楚了。

以上是关于使用基于属性的过滤子元素集获取核心数据实体的主要内容,如果未能解决你的问题,请参考以下文章

核心数据 - 使用数组的确切元素获取对象过滤数据

获取具有类名的字段集的所有子输入元素,输入元素只是字段集的间接子元素

获取“最新”单个实体的最简单 Fetch 请求 - 核心数据

子查询谓词核心数据

vue学习--父元素如何获取子元素的值,子元素如何获取父元素的值

获取核心数据实体,但不获取子实体