我在请求上使用NSFetchedResultsController
和sortDescriptors
填充具有很多结果的表。我注意到,当发生更改将一行从表底部附近移到顶部时,根本没有调用didChangeObject:atIndexPath:forChangeType:newIndexPath:
。
奇怪的是,我可以通过遍历所有提取的对象并在调用performFetch
之后立即访问它们的任何属性来解决此问题。
关于问题可能是什么的任何提示,或者这仅仅是一个晦涩的Apple错误?
这是我的代码:
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@"MyObject" inManagedObjectContext:context];
request.sortDescriptors = @[NSSortDescriptor sortDescriptorWithKey:@"order" ascending:NO]];
request.fetchBatchSize = 20;
NSFetchedResultsController *fetched = [[NSFetchedResultsController alloc]
initWithFetchRequest:request
managedObjectContext:context
sectionNameKeyPath:nil
cacheName:nil];
fetched.delegate = self;
NSError *error = nil;
if (![fetched performFetch:&error]) {
NSLog(@"Unresolved error fetching objects: %@", error);
}
// Should not be necessary, but objects near the bottom won't move to the top without it.
for (MyObject *o in fetched.fetchedObjects) {
o.someAttribute;
}
2014年9月12日更新:
我将所有数据保存在后台托管对象上下文中,这似乎与我看到的问题有关。这是我的代码,用于合并从到主对象上下文的更改:
+(void)initSaveListener {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification
object:[self privateContext]];
}
+(void)mergeChanges:(NSNotification*)notification {
NSManagedObjectContext *context = [self mainContext];
[context performBlock:^{
[context mergeChangesFromContextDidSaveNotification:notification];
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"error merging changes %@, %@", error, [error userInfo]);
}
}];
}
最佳答案
事实证明,此问题是由于managedObjectContext
的更改是使用NSManagedObjectContextDidSaveNotification
从另一个上下文传播而来的。这篇博客文章详细解释了为什么这会导致NSFetchedResultsController
问题,以及如何解决该问题:
http://www.mlsite.net/blog/?p=518
这是我上面的代码上下文中的特定修复程序:
+(void)mergeChanges:(NSNotification*)notification {
NSManagedObjectContext *context = [self mainContext];
// Fault all objects that have changed so that NSFetchedResultsController will see the changes.
NSArray *objects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];
for (NSManagedObject *object in objects) {
[[context objectWithID:[object objectID]] willAccessValueForKey:nil];
}
[context performBlock:^{
[context mergeChangesFromContextDidSaveNotification:notification];
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"error merging changes %@, %@", error, [error userInfo]);
}
}];
}
关于ios - NSFetchedResultsController并不总是为NSFetchedResultsChangeMove调用didChangeObject:atIndexPath:forChangeType:newIndexPath:,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25588624/