核心数据:使用 SQLITE 存储类型时,包含对多关系的 NSPredicate 不会产生任何结果

Posted

技术标签:

【中文标题】核心数据:使用 SQLITE 存储类型时,包含对多关系的 NSPredicate 不会产生任何结果【英文标题】:Core Data: NSPredicate containing to-many relationship yields no results when using SQLITE store type 【发布时间】:2011-01-24 16:18:40 【问题描述】:

直到最近,我一直在为我的项目使用带有内存存储的 Core Data。现在我正在尝试切换到 SQLite 商店,但遇到了以下问题:

当尝试使用谓词和 sortDescriptor 从存储中获取对象时,我的 fetchedResultsController 返回 0 个对象。当存储类型为内存时,完全相同的代码可以正常工作。

这就是我进行抓取的方式:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY %K == %@", @"categories", category];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES selector:@selector(caseInsensitiveCompare:)];
self.fetchedResultsController = [self createFetchedResultsControllerWithEntityName : @"Provider" sectionName : @"group" sortDescriptor : sortDescriptor predicate : predicate cache : nil];

NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
       

[self.tableView reloadData];

这是我创建获取请求的地方:

- (NSFetchedResultsController *)createFetchedResultsControllerWithEntityName : (NSString*) entityName sectionName : (NSString*) sectionName sortDescriptor : (NSSortDescriptor*) sortDescriptor predicate : (NSPredicate*) predicate cache : (NSString*) cacheName 

// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];

NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

[fetchRequest setSortDescriptors:sortDescriptors];

//set predicate 
if (predicate)
    [fetchRequest setPredicate:predicate]; 

// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                                                                                                managedObjectContext:managedObjectContext 
                                                                                              sectionNameKeyPath:sectionName 
                                                                                                       cacheName:cacheName];
aFetchedResultsController.delegate = self;

[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];


return [aFetchedResultsController autorelease];

同样,同样的代码在使用内存存储时会获取许多对象,但在使用 SQLite 时会获取一个空的 fetchedObjects 数组。

我已经阅读了 Apple 的文档,了解在 SQLite 存储中使用谓词和 sortDescritors 时要考虑的特殊注意事项。我在谓词中使用单个(多)对多关系(类别),所以这应该没问题吗?

提取没有返回错误。根本没有对象(fetchedResultsController.fetchedObjects 是空的)。

任何指导将不胜感激。

谢谢

【问题讨论】:

【参考方案1】:

我终于弄清楚了这个问题。

我的查询没有返回结果,确实没有结果。追溯到我创建对象并用值填充关系的地方,我注意到我做错了。我试着做:

[provider.categories addObject : newCategory];

这并没有真正将 newCategory 添加到类别关系中。 在意识到 Core Data 会自动生成对多关系的访问器后,我使用以下内容添加了 newCategory:

[provider addCategoriesObject : newCategory];

这会正确地将 newCategory 添加到关系中。

除此之外,我在 Provider.h 中声明了 addCategoriesObject 以抑制编译器警告。这为我解决了这个问题。

唯一剩下的警告是编译器没有找到 addCategoriesObject: 的实现,并警告“不完整的实现”。我还没有想出办法来抑制这个警告。

【讨论】:

【参考方案2】:

我知道 SQLite 存储在某些情况下会遇到 "ANY" 提取问题(我不记得确切的那些)。也许尝试修改你的搜索谓词,看看你是否得到不同的结果,例如

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"categories LIKE %@", category];

【讨论】:

以上是关于核心数据:使用 SQLITE 存储类型时,包含对多关系的 NSPredicate 不会产生任何结果的主要内容,如果未能解决你的问题,请参考以下文章

预填充核心数据存储:使用 JSON 属性列表还是 XML 文件?

核心数据/SQLite 存储偶尔数据丢失

Lion 中的 sqlite 核心数据存储在哪里? [复制]

核心数据 SQLite 加密?

在核心数据中搜索所有具有空“对多”关系的对象

使用 iOS 应用发送核心数据