仅获取共享特定属性值的 Core Data 对象

Posted

技术标签:

【中文标题】仅获取共享特定属性值的 Core Data 对象【英文标题】:Fetching only Core Data objects that share a value for a particular attribute 【发布时间】:2014-04-28 23:57:30 【问题描述】:

我有一个包含多个属性的 Core Data 对象,其中一个称为 Category。这是一个可以取任何值的字符串,我不能保证预先知道任何知识。我想运行一个提取,它将返回一个类别值列表,这些值在其标记值与给定值匹配的所有存储元素之间共享。我不确定如何最好地描述这一点,所以这里有一个例子:

ObjectNumber     Tag     Category
---------------------------------
01               AAA     Red
02               AAA     Green
03               AAA     Blue

04               BBB     Blue
05               BBB     Red
06               BBB     Yellow

07               CCC     Blue
08               CCC     Yellow
09               CCC     Red

我希望获取的结果是一个类别列表,这些类别在其标签位于集合 AAA, BBB, CCC 中的所有对象之间共享,在这种情况下,它将返回 ["Red", "Blue "],因为这些是标签在给定集合中的任何对象之间共享的唯一类别。

我希望尽可能快地找到一些东西,因为当这个应用程序在一个真实的项目上运行时,数据库中会有数以万计的对象。

【问题讨论】:

Phil 您是否尝试过使用NSPredicate 进行抓取? 我有,但我不知道如何设置它以将结果限制在我需要的范围内。 我认为这需要超越 NSPredicate 进入 SQL,以便简单地获取作为一组获取对象的属性的字符串数组。否则,处理 NSPredicate 的结果。根据我对 NSFetchRequest 和其他 Core Data 事物的有限研究,Apple 建议进行后处理以获得更细粒度的结果。 Tom,这就是我在 android 中实现这一目标的方式。我希望找到一种方法来使用谓词,但我觉得你是对的。 @PhilRingsmuth 我会尽快发布答案! :) 【参考方案1】:

这是我刚刚编写的代码示例,应该可以解决您的过滤问题。

在阅读文档和实验之后,我仍在学习 NSFetchRequest 和谓词的复杂性,虽然不是很复杂。

NSArray *setoftags = [NSArray arrayWithObjects: @"AAA", @"BBB", nil];
NSFetchRequest * request;
NSMutableSet *tagcategoriesset = nil;
for (NSString *tag in setoftags) 

    request = [NSFetchRequest fetchRequestWithEntityName:@"ObjectWithCategories"];
    NSPredicate *tagPredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"Tag", tag];
    request.predicate = tagPredicate;
    NSArray *objects;
    NSError *err;
    NSMutableSet *tagcategories = [[NSMutableSet alloc] initWithCapacity:1];
    if ( (objects = [self.managedObjectContext executeFetchRequest:request error:&err]) == nil) 
        // error
        NSLog(@"There was an error:\n%@", [err localizedDescription]);
    
    else 
        // fetch request succeeded


        // Ignore any unused tags
        if ( [objects count] == 0) continue;

        // Collect the Category attribute into a mutable set
        for(NSManagedObject *obj in objects) 
            [tagcategories addObject: [(id)obj Category]];
        

        // First assign, later intersect the tagcategories
        if (tagcategoriesset == nil) 
            tagcategoriesset = tagcategories;
        
        else 
            [tagcategoriesset intersectSet: tagcategories];
        
    


NSArray *finalCategories = [tagcategoriesset allObjects];

这是另一个 SO Q&A 供进一步讨论:using NSPredicate with a set of answers

【讨论】:

谢谢汤姆。这看起来会让我走上正轨。 @PhilRingsmuth 我刚刚浏览了 andrewbuilder 的代码,它错过了跨标签类别的集体唯一性,但我的也是。给我一点时间。 :) @TomPace 是的,它错过了,但要清楚的是,我的代码是作为示例提供的,可以从中推断出解决方案。也许我应该在回答中更清楚地说明这一点? @andrewbuilder 也许看到一个更清晰的答案会很酷,但我已经重新阅读了这个问题,并且存在一个尴尬的逻辑关系,一个多对多的关系与一个 in - 动态构建内存表。 @TomPace 公平评论。我也会看看它,看看我是否可以将NSPredicate 争吵成一个解决方案。【参考方案2】:

这些都是帮助我更好地理解NSPredicate的好文章。我强烈推荐这些值得一读。

Apple Documentation

NSHipster 马特·汤普森

Using NSPredicate to Filter Data by Peter Friese


这是一个简单的NSPredicate...的示例...

NSString *key = @"Category";
NSString *value = @"Red";
[NSPredicate predicateWithFormat:@"%K == %@", key, value]

这是一个更复杂的NSPredicate...的示例...

NSString *key = @"Category";
NSString *value1 = @"Red";
NSString *value2 = @"Blue";
NSPredicate *predicateRed = [NSPredicate predicateWithFormat: @"%K == %@", key, value1];
NSPredicate *predicateBlue = [NSPredicate predicateWithFormat: @"%K == %@", key, value2];
NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[predicateRed, predicateBlue]];

我使用这种格式来演示可以实现的目标。为了清楚起见,第二个示例也可以更简单地编写...

NSPredicate *predicate = [NSPredicate predicateWithFormat: @"(%K == %@) || (%K == %@)", key, value1, key, value2];

这些示例并非旨在成为解决方案,而是提供帮助您开发解决方案的机制。

希望对您有所帮助。

【讨论】:

以上是关于仅获取共享特定属性值的 Core Data 对象的主要内容,如果未能解决你的问题,请参考以下文章

有没有比获取请求更快的方法来检索 Core Data 中的特定托管对象?

如何从对象数组中获取具有属性的列表,除非它包含具有特定值的另一个项目?

在 Core Data 中为获取的属性设置限制

如何根据相关对象集合的属性对 Core Data 结果进行排序?

在 Core Data 中更改托管对象模型的属性值时崩溃

JavaScript:删除共享相同属性值的对象的重复项