这是另一种情况,在performFetch
上调用NSFetchedResultController
时会出现例外情况:
致命错误:部分信息的持久缓存与当前配置不匹配。您已经非法改变了NSFetchedResultsController的获取请求,其谓词或其排序描述符,而没有禁用缓存或使用+ deleteCacheWithName:
除非我没有做过这些。要了解问题,请查看谓词:
谓词:(collection.identifier ==&#34 ;; root" AND doc.status == 0);
现在查看不匹配的缓存内容:
cached objects were: (
"MyDocument 'PL00002.jpeg' in set '/' (#2147483647)",
"MyDocument 'PL00003.jpeg' in set '/' (#2147483647)",
"MyDocument 'PL00003.pdf' in set '/' (#2147483647)",
"MyDocument 'PL00002.pdf' in set '/' (#2147483647)"
)
fetched objects are: (
"MyDocument 'PL00002.jpeg' in set '/' (#2147483647)",
"MyDocument 'PL00003.jpeg' in set '/' (#2147483647)",
"MyDocument 'PL00004.jpeg' in set '/' (#2147483647)",
"MyDocument 'PL00003.pdf' in set '/' (#2147483647)",
"MyDocument 'PL00002.pdf' in set '/' (#2147483647)",
"MyDocument 'PL00004.pdf' in set '/' (#2147483647)"
)
实际上,有两个新的匹配对象。原因是两个新对象(PL00004.jpeg
和PL00004.pdf
)先前已将status
属性设置为值<> 0并将其status
更改回0在代码中,因为它们开始满足某些外部条件(不是由用户操作触发)。
为了完整性,以下是触发异常的代码:
- (void) reloadData
{
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
abort(); // I have actually better error handling
}
[_gridView reloadData];
}
还要注意:
NSFetchedResultController
使用名称相同的缓存_gridView
不是UITableView
,但它也会显示实体集合。这个细节不应该相关。NSFetchedResultController
委托方法,尤其是在我将两个对象的状态更改为0时performFetch:
之前清空缓存(或没有缓存),一切都运行正常。reloadData
方法,以了解上面提到的外部条件。NSFetchedResultController
是使用 nil
sectionNameKeyPath
创建的。fetchedResultsController
:不是它的谓词,不是它的获取请求,而不是它的排序顺序,没有。 我认为我不应该仅仅因为新对象现在满足谓词而得到此异常。删除缓存可以避免例外,但只要我不理解为什么要这样做,我就不会将其视为修复。
知道我想念的是什么吗?
编辑:这是请求的信息:
设置NSFetchedResultController
的代码。当用户选择一个集合时,这称为:
- (void) displayCollection:(Collection *)aSet
{
self.currentCollection = aSet;
NSFetchRequest *fetchRequest = [[self fetchedResultsController] fetchRequest];
NSString *collectionIdentifier = @";root"; // no selection is like "select root collection";
if (aSet) {
collectionIdentifier = aSet.identifier;
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"collection.identifier == %@ and doc.status == %d", collectionIdentifier, upToDate];
[fetchRequest setPredicate:predicate];
[NSFetchedResultsController deleteCacheWithName:cacheName];
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
abort(); // whatever
}
[_gridView reloadData];
}
fetchedResultsController
因此被初始化:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"DocInCollection" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"collection.identifier == %@ and doc.status == %d", @";root", upToDate];
[fetchRequest setPredicate:predicate];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"position" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:cacheName];
更新doc.status
时调用的代码:
- (void) setUpToDate
{
self.status = [NSNumber numberWithInt:upToDate];
NSError *error = nil;
[[self managedObjectContext] save:&error];
if (error) { } // whatever
[[self managedObjectContext] processPendingChanges];
}
cacheName
是全局const NSString
,upToDate
是枚举常量(0)。
最后,由于应用程序使用的其他实体,模型有点复杂。这是一个简化版本:
model http://emberapp.com/jdmuys/images/untitled-1/sizes/m.png
答案 0 :(得分:0)
我会查看你的sectionNameKeyPath
及其与被变异属性的关系(如果有的话)。从错误消息中可以看出,您的部分正在以控制器不喜欢的方式进行更改。
不确定它是否完全相关,但我会对任何带有未转义分号的声明感到紧张。那个谓词位";root"
给了我一个痒。当然,它的任何问题都应该在编译时出现,但仍然......
出于病态的好奇,我用上面的方法将测试数据模型和一些代码拼凑在一起。以下甚至不会编译:
NSManagedObject *cMO=[NSEntityDescription insertNewObjectForEntityForName:@"Collection" inManagedObjectContext:self.moc];
NSManagedObject *dMO=[NSEntityDescription insertNewObjectForEntityForName:@"Doc" inManagedObjectContext:self.moc];
[cMO setValue:@";root" forKey:@"identifier"];
[dMO setValue:[NSNumber numberWithInt:0] forKey:@"status"];
[cMO setValue:dMO forKey:@"doc"];
NSFetchRequest *fetch=[[NSFetchRequest alloc] init];
[fetch setEntity:[NSEntityDescription entityForName:@"Collection" inManagedObjectContext:self.moc]];
NSPredicate *p=[NSPredicate predicateWithFormat:@"identifier==";root" AND doc.status==0"];
[fetch setPredicate:p];
NSArray *a=[self performFetch:fetch];
NSLog(@"%@",a);
将谓词更改为:
NSPredicate *p=[NSPredicate predicateWithFormat:@"identifier == ';root' AND doc.status == 0"];
...编译并正常工作。我建议您至少将";root"
更改为';root'
进行问题排查。