NSFetchedResultsController不总是调用didChangeObject:atIndexPath:forChangeType:newIndexPath:for NSFetchedResultsChangeMove [英] NSFetchedResultsController doesn't always call didChangeObject:atIndexPath:forChangeType:newIndexPath: for NSFetchedResultsChangeMove

查看:111
本文介绍了NSFetchedResultsController不总是调用didChangeObject:atIndexPath:forChangeType:newIndexPath:for NSFetchedResultsChangeMove的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在请求中使用 NSFetchedResultsController sortDescriptors 来填充表中有很多结果。我注意到,当发生更改,从一个行从底部附近移动到顶部, didChangeObject:atIndexPath:forChangeType:newIndexPath:根本不调用。 / p>

奇怪的是,我可以通过遍历所有获取的对象并访问任何属性,直接调用 performFetch



有关问题可能出现的任何提示,或者这只是一个模糊的苹果错误?



这是我的代码:

  NSManagedObjectContext * context = [self managedObjectContext]; 
NSFetchRequest * request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@MyObjectinManagedObjectContext:context];
request.sortDescriptors = @ [NSSortDescriptor sortDescriptorWithKey:@orderascending: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(@未解决的错误提取对象:%@,错误)
}

//不应该是必需的,但是底部附近的对象不会移动到顶部。
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 userInfo]);
}
}];
}


解决方案

是由 managedObjectContext 的变化是使用 NSManagedObjectContextDidSaveNotification 从另一个上下文传播的事实造成的。这篇博文详细解释了为什么这会导致 NSFetchedResultsController 的问题,以及如何解决它:



http://www.mlsite.net/blog/?p=518



这里是我上面代码上下文中的具体修复:

  + void)mergeChanges:(NSNotification *)notification {
NSManagedObjectContext * context = [self mainContext];

//断开所有已更改的对象,以便NSFetchedResultsController将看到更改。
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 userInfo]);
}
}];
}


I'm using NSFetchedResultsController with sortDescriptors on the request to populate a table with a lot of results in it. I notice that when a change occurs that moves a row from near the bottom of the table to the top, didChangeObject:atIndexPath:forChangeType:newIndexPath: is not called at all.

Strangely, I can work around this by iterating through all the fetched objects and accessing any attribute on them right after calling performFetch.

Any tips on what the problem might be, or is this just an obscure Apple bug?

Here is my code:

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;
}

Updated September 12, 2014:

I'm saving all data in a background managed object context, and it seems to be related to the issues I'm seeing. Here is my code for merging changes from to the main object context:

+(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]);
        }
    }];
}

解决方案

It turns out that this problem was caused by the fact that the changes to managedObjectContext were being propagated from another context using NSManagedObjectContextDidSaveNotification. This blog post explains in detail why this causes a problem for NSFetchedResultsController, and how to fix it:

http://www.mlsite.net/blog/?p=518

Here is the specific fix in the context of my code above:

+(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]);
        }
    }];
}

这篇关于NSFetchedResultsController不总是调用didChangeObject:atIndexPath:forChangeType:newIndexPath:for NSFetchedResultsChangeMove的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆