使用 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 中的空格。如何修剪谓词?