用于ListView的iOS复杂查询

时间:2013-04-19 19:22:10

标签: ios core-data

我有一个模型:

Place:
title
address
category <--->> Category:
                title

我希望有一个表格视图,其中的部分作为类别名称,但能够根据地点标题进行搜索。现在,为表视图获取一组数据的最佳方法是什么,该表视图只包含与某些指定searchText匹配的类别和标题?我目前正在将结果放在NSDictionary中,但它看起来效率不高。特别是在执行删除类型操作时 - 我遇到了很多问题。目前我正在做以下事情,但woudl更直接返回FetchedResultsController。

+ (NSMutableDictionary *)getDictionaryResultsInContext: (NSManagedObjectContext *)context
                                         forSearchText: (NSString *)searchText {

    NSFetchRequest *req = [NSFetchRequest fetchRequestWithEntityName:@"Place"];
    if(![searchText isEqualToString:@""] && searchText != nil){
        req.predicate = [NSPredicate predicateWithFormat:@"(category.name CONTAINS[cd] %@) OR (placeTitle CONTAINS[cd] %@) OR (details CONTAINS[cd] %@)", searchText, searchText, searchText];
        NSLog(@"ModelHelper.getResults: Search text given, creating predicate: %@", req.predicate);
    }
    req.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"placeTitle"
                                                                                 ascending:YES
                                                                                  selector:@selector(localizedCaseInsensitiveCompare:)]];
    NSFetchedResultsController *controller = [[NSFetchedResultsController alloc]initWithFetchRequest:req
                                                                                managedObjectContext:context
                                                                                  sectionNameKeyPath:nil
                                                                                           cacheName:nil];
    NSError *error = nil;
    [controller performFetch:&error];
    if (error) {
        NSLog(@"- Model Search ERROR: %@ (%@)", [error localizedDescription], [error localizedFailureReason]);
    }

    NSLog(@"- Got results: %i", [controller.fetchedObjects count]);

    NSMutableDictionary* ret = [[NSMutableDictionary alloc]init];

    for(Place* obj in controller.fetchedObjects){
        if(obj != nil){
            NSManagedObjectID* categoryId = obj.category.objectID;
            if(categoryId != nil){
                NSMutableArray* ary = (NSMutableArray*)[ret objectForKey:categoryId];
                if(ary == NULL){
                    ary = [[NSMutableArray alloc]init];
                    [ret setObject:ary forKey:categoryId];
                }
                [ary addObject:obj];
            }
            else {
                // Shouldnt happen
                NSLog(@"- Category was nil.");
            }
        }
        else {
            // Shouldnt happen
            NSLog(@"- Place was nil.");
        }
    }

    return(ret);
}

1 个答案:

答案 0 :(得分:0)

您的数据模型没有意义。你真的想要一个多对多的关系。

如果类别可以包含多个地方,那么它们才有意义。所以category->place关系必须是多对的。可选地,一个地方可以在多个类别中,因此place->category也可以是多个;如果不是它应该是一对一的关系。

所以要么

Place <<----------> Category

Place <<--------->> Category

但不是您问题中的版本。在您的场景中,作为餐厅的地方将获得标题为“餐厅”的类别,而对于下一个餐厅,您将需要创建标题为“餐厅”的新类别。没有意义。

在简单的情况下(一对多),您的谓词是

[NSPredicate predicateWithFormat:
  @"title CONTAINS[cd] %@ OR address CONTAINS[cd] %@", searchTerm, searchTerm];

对于更复杂的情况(多对多),您遇到的问题是可以在多个部分中列出地点。因此,您必须获取类别,使用类别位数作为每个部分中的行数,并使用此谓词进行过滤:

[NSPredicate predicateWithFormat:
  @"ANY places.title CONTAINS[cd] %@ OR ANY places.address CONTAINS[cd] %@",
  searchTerm, searchTerm];