使用 NSPredicate contains 在 coredata 实体的字段中查找字符

Posted

技术标签:

【中文标题】使用 NSPredicate contains 在 coredata 实体的字段中查找字符【英文标题】:using NSPredicate contains to find characters inside a coredata entity's field 【发布时间】:2011-03-17 07:19:35 【问题描述】:

我正在尝试查找包含特定字母序列的所有客户。我想要与 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 个元素。我什么也没得到。

我尝试将数据库转储到控制台,其中包含所有正确的内容。帮助!!!

=更新========================================== ============

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

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

它在 NSLog(@"%Matches: line里面好像没有东西。

【问题讨论】:

【参考方案1】:

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

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

当你传入fieldKey = @"fullname"value = @"matt" 时,这个谓词将等价于:

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

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

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

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

这就是你要找的东西。

【讨论】:

感谢您的回答。信不信由你,我以前尝试过 %K,但没有结果。整个“关键路径”的事情让我感到震惊,因为我正在搜索的实体上的列不是“关键”字段。无论如何,我将它改回 %K 并且程序仍然......以一种奇怪的方式冻结。就像我在那里有一个调试指针,但没有。我的数据库中只有 6 个项目。 请查看我的更新区。谢谢你【参考方案2】:

从您命名变量和参数的方式可以看出,您是用 SQL 术语来思考的。核心数据不是 SQL。实体不是表格。对象不是行。列不是属性。 Core Data 是一个对象图管理系统,它可能会也可能不会持久化对象图,并且可能会或可能不会在幕后使用 SQL 来做到这一点。试图用 SQL 术语来思考 Core Data 会导致您完全误解 Core Data 并导致很多痛苦和浪费时间。

在这个区块中:

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");

【讨论】:

【参考方案3】:

我忘记在我的一个辅助方法中返回 NSArray。

【讨论】:

以上是关于使用 NSPredicate contains 在 coredata 实体的字段中查找字符的主要内容,如果未能解决你的问题,请参考以下文章

NSPredicate:将 CONTAINS 与 IN 结合

NSPredicate,CoreData 中的空格。如何修剪谓词?

带有特殊字符的 NSPredicate 过滤

CloudKit NSPredicate 不区分大小写

NSPredicate 101:将 NSPredicate 与自定义对象的 NSMutableArray 一起使用

如何使用 NSPredicate 在字符串中查找开头的单词?