使用NSPredicate包含查找核心数据实体字段内的字符

时间:2011-03-17 07:19:35

标签: iphone core-data ios4 nspredicate

我正在尝试查找包含特定字母序列的所有客户。我想要与NSString的rangeofString相同的功能,除了不区分大小写。继承我的方法:

-(NSArray *) db_search: (NSString *) table where: (NSString*) fieldKey contains: (NSString*) value withSortField: (NSString *) sortField{
    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
    NSEntityDescription *entity = [NSEntityDescription entityForName:table inManagedObjectContext:context];
    if (fieldKey != nil){
        NSPredicate *predicate = [NSPredicate
                                  predicateWithFormat:@"(%@ contains[c] %@)",
                                  fieldKey,value];
        [request setPredicate:predicate];
    }
    [request setEntity:entity];

    if (sortField != nil){
        NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:[self extractSortField:sortField] ascending:[self isAscending:sortField]] autorelease];
        NSArray *sortDescriptors = [[[NSArray alloc] initWithObjects:sortDescriptor, nil] autorelease];
        [request setSortDescriptors:sortDescriptors];
    }

    NSError *error;
    return [context executeFetchRequest:request error:&error];
}

我用这些值来称呼它:

NSArray * results = [self db_search:@"Customer" where:@"fullname" contains:@"matt" withSortField:nil];

当我尝试打印出结果时,它会冻结而不是得到所有Matts,Matthews等。我调试了它,我们甚至没有得到一个空的NSArray。我打印NSArray到控制台,我没有得到0元素..我什么都没得到。

我尝试将数据库转储到控制台,它包含所有正确的内容。救命!!!

= UPDATE ========================================== ============

我正在使用%K而且我遇到了一个奇怪的运行时错误:

if (searchResults1 != nil){
    NSLog(@"%Matches: %i", [searchResults1 count]);
}else {
    NSLog(@"Was NULL");
}

它在NSLog上(@“%匹配:行。它是一个坏的EXC错误。所以searchResults1不是nill但是当我尝试读取计数时它会崩溃吗?当我调试时,searchResults1确实是一个NSArray但它没有'似乎里面有任何东西。

3 个答案:

答案 0 :(得分:13)

看起来你的问题是你的谓词:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(%@ contains[c] %@)", fieldKey,value];

当您传入fieldKey = @"fullname"value = @"matt"时,此谓词将等同于:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"('fullname' contains[c] 'matt')"];

你看到了问题吗?它将“fullname”视为原始字符串,而不是字段的名称。这是因为您在格式字符串中使用了%@修饰符。当NSPredicate遇到这些时,它会说“啊哈!这里取代的价值将是一个常数”。你真正想要它做的是说“啊哈!这里取代的价值将是一个标识符”。

因此,不要使用%@,而是使用%K。这是一个仅用于谓词的特殊修饰符,它意味着在字符串中替换为标识符(实际上是“keypath”),这意味着它将使您的谓词成为:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(fullname contains[c] 'matt')"];

您正在寻找的是什么。

答案 1 :(得分:1)

我可以从您用SQL术语命名的变量和参数的命名方式来判断。核心数据不是SQL。实体不是表格。对象不是行。列不是属性。核心数据是一个对象图管理系统,可能会或可能不会持久保存对象图,并且可能会或可能不会使用远远落后的SQL来执行此操作。试图用SQL术语来思考核心数据将导致你完全误解核心数据并导致更多的悲伤和浪费时间。

在这个块中:

if (searchResults1 != nil){
    NSLog(@"%Matches: %i", [searchResults1 count]);
}else {
    NSLog(@"Was NULL");
}

......你这里有两个问题。首先,searchResults1永远不会是零。无论fetch是否找到任何对象,它都将返回一个数组对象。相反,您应该检查数组的计数。其次,%Matches是一个错字。 %是格式控制字符,将使编译器查找控制代码,例如紧接着%@。试试这个:

if ([searchResults1 count]>0){
    NSLog(@"Matches: %i", [searchResults1 count]);
}else {
    NSLog(@"No managed objects found");
}

答案 2 :(得分:0)

我忘了用我的一个辅助方法返回NSArray。