【问题标题】:Fetching only Core Data objects that share a value for a particular attribute仅获取共享特定属性值的 Core Data 对象
【发布时间】: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 我会尽快发布答案! :)

标签: ios objective-c core-data nspredicate nsfetchrequest


【解决方案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];

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

希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-31
    • 2012-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多