使用 Coredata 和 NSFetchRequest 进行“IN”搜索时如何格式化 NSPredicate

Posted

技术标签:

【中文标题】使用 Coredata 和 NSFetchRequest 进行“IN”搜索时如何格式化 NSPredicate【英文标题】:How To Format NSPredicate when doing an "IN" search with Coredata and NSFetchRequest 【发布时间】:2013-08-16 12:01:47 【问题描述】:

我有一个非常简单的获取请求,我想执行它。我的一个实体有一个名为 smartCollectionIds 的属性,它是可转换的类型。我使用此属性来存储简单字符串的NSArray。在我的代码中,我使用NSfetchedResultsController 来填充表格视图。 im 使用的谓词如下:

predicate=[NSPredicate predicateWithFormat:@"smartCollectionIds!=nil && (%@ IN smartCollectionIds)",@"87F173A5-863D-4ECE-9673-A61D8F1E01FC-6285-000009A9CBAF3290"];

但是这会导致崩溃,特别是在我执行提取时。但是,如果我首先使用 fetch 将我的所有对象加载到一个数组中,然后使用上述谓词将它们过滤掉,则应用程序不会崩溃,并且我会得到预期的结果。所以基本上 下面的代码不起作用

-(void) tryTO

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Tweetary" inManagedObjectContext: [[ChubbyEyetwitterEngine sharedInstance] getManagedObjectContextForUse]];

NSPredicate *predicate;

predicate=[NSPredicate predicateWithFormat:@"smartCollectionIds!=nil && (%@ IN smartCollectionIds)",@"87F173A5-863D-4ECE-9673-A61D8F1E01FC-6285-000009A9CBAF3290"];

NSSortDescriptor *secondarySortKey = [[[NSSortDescriptor alloc] initWithKey:@"created_at" ascending:FALSE] autorelease];

NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease] ;
[request setEntity:entity];
[request setPredicate:predicate];
[request setSortDescriptors:[NSArray arrayWithObjects:
                             secondarySortKey
                             ,nil]];
[request setFetchLimit:30];  //30


NSError *error;

NSArray *results = [[[ChubbyEyetwitterEngine sharedInstance] getManagedObjectContextForUse] executeFetchRequest:request error:&error];

if (error != nil)

     NSLog(@"Results are %d",[results count]);

else
    NSLog(@"findAllObjectsInContext error %@",error);


但这有效

  NSArray *tweets = [Tweetary findAllObjectsInContext:[[ChubbyEyetwitterEngine sharedInstance] getManagedObjectContextForUse]];

NSLog(@"Before filter count is %d",[tweets count]);

predicate=[NSPredicate predicateWithFormat:@"smartCollectionIds!=nil && (%@ IN smartCollectionIds)",@"87F173A5-863D-4ECE-9673-A61D8F1E01FC-6285-000009A9CBAF3290"];

predicate=[NSPredicate predicateWithFormat:@"smartCollectionIds!=nil && (%@ IN smartCollectionIds)",@"87F173A5-863D-4ECE-9673-A61D8F1E01FC-6285-000009A9CBAF3290"];

NSArray *bNames = [tweets filteredArrayUsingPredicate:predicate];

NSLog(@"FINAL Results %d",[bNames count]);



+ (NSArray *)findAllObjectsInContext:(NSManagedObjectContext *)context;
  


 @synchronized(self)

NSEntityDescription *entity = [self entityDescriptionInContext:context];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entity];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
if (error != nil)

    //handle errors
    //NSLog(@"findAllObjectsInContext error %@",error);

return results;
  
 

简而言之,在使用 NSfetchedResultsController 时,我需要我的 fetch 谓词才能工作,而不是先将我的对象加载到数组中,然后再应用我的过滤谓词。谁能指出我正确的方向/弄清楚为什么谓词只有在我将未过滤的数据集加载到数组后才有效?

【问题讨论】:

【参考方案1】:

带有谓词的核心数据获取请求被转换为 SQLite 查询并执行 在 SQLite 级别。一个可转换的数组作为一些 blob 存储在 SQLite 数据库中, 因此在 fetch 请求中将其视为数组是行不通的。

如果您先获取元素,则 blob 将转换回数组 访问该属性时。因此过滤获取的对象数组按预期工作。

我认为没有任何解决方法。您不能过滤可转换的属性 在获取请求中。

【讨论】:

以上是关于使用 Coredata 和 NSFetchRequest 进行“IN”搜索时如何格式化 NSPredicate的主要内容,如果未能解决你的问题,请参考以下文章

核心数据:NSManagedObjectContext 未保存/获取请求失败,直到应用退出和重新启动

Coredata — 入门使用

CoreData:按创建的顺序获取和排序结果,不使用时间戳

Coredata 和 Mogenerator,coredata 标志并发问题 EXC_BAD_INSTRUCTION

将 UICollectionView 与 CoreData 和 NSFetchedResultsController 一起使用

如何一起使用Codable和Coredata?