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

时间:2014-04-28 23:57:31

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

我有一个具有多个属性的Core Data对象,其中一个属性称为Category。这是一个可以承担任何价值的字符串,我无法保证任何预先知识。我想运行一个fetch,它将返回一个Category值列表,这些值在Tag值与给定值匹配的所有存储元素之间共享。我不确定如何最好地描述这一点,所以这是一个例子:

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

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

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

2 个答案:

答案 0 :(得分:2)

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

在阅读文档和试验之后,我仍在学习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

答案 1 :(得分:1)

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

Apple Documentation

Mattt Thompson的

NSHipster

Peter Friese的

Using NSPredicate to Filter Data


这是简单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];

这些示例并不是解决方案,但是用于演示帮助您开发解决方案的机制。

希望有所帮助。