【问题标题】:Coredata - "NSObjectInaccessibleException - CoreData could not fulfill a fault"Coredata - “NSObjectInaccessibleException - CoreData 无法完成故障”
【发布时间】:2011-08-01 06:27:23
【问题描述】:

我是 Core data 的新手,仍在搞清楚具体细节,这个错误已经困扰了我好几个小时,我似乎找不到解决方案。非常感谢任何帮助。

问题是这样的

我有两个从服务器获取数据和更新 UI 的视图。我已经这样设置了流程

view1 -> 从服务器发送 HTTP 请求 - 接收回调 -> 将数据保存到 Coredata -> 从 Core Data 读取并显示在 UI 上(回调和保存/读取 Coredata 发生在 ViewController 中)

view2 -> 从服务器发送 HTTP 请求 - 接收回调 -> 将数据保存到 Coredata -> 从 Core Data 读取并显示在 UI 上(回调和保存/读取 Coredata 发生在 ViewController 中)

视图 2 每 3 秒重复一次此过程,因为这是一个自动刷新屏幕。

问题是每当我尝试在视图 1 和 2 之间快速切换时,应用程序都会因上述错误而崩溃。如果我在每个视图上等待几秒钟(等待从服务器获取数据),它工作正常。我做错了什么,我需要修改什么?

- (void) refreshData {
    [super refreshData];
    [[UserDataFactory sharedSingleton] refreshLoggedInUserDataAndRespondTo:self user:self.user];
}

- (BOOL) refreshDataCallback:(QExtendedHTTPOperation*)responseOperation {
    [self saveToCoreData: responseOperation.responseArray];
    NSMutableArray *tmp = [[NSMutableArray alloc] initWithArray:[self readFromCoreData]];
    [self setData: tmp];
    [tmp release];
    [self.tableView reloadData];
    return YES;
}

- (void) saveToCoreData:(NSArray *) responseArray{
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"CoreView1" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];
    [fetchRequest setReturnsObjectsAsFaults:NO];
    NSError *error;
    NSArray *items = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    [fetchRequest release];

    for (NSManagedObject *managedObject in items) {
            [self.managedObjectContext deleteObject:managedObject];
    }

    for (int i=0; i<[responseArray count]; i++) {
            CoreView1 *coreView1_ = [NSEntityDescription insertNewObjectForEntityForName:@"CoreView1" inManagedObjectContext:self.managedObjectContext];
            coreView_.id = [[responseArray objectAtIndex:i] id];    
            [self.managedObjectContext insertObject:coreView1_];
    }
    [self saveContext:self.managedObjectContext];
}

- (NSArray *) readFromCoreData{ 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"CoreView1" inManagedObjectContext:self.managedObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:entity];
    [fetchRequest setReturnsObjectsAsFaults:NO];
    NSError *error;
    NSMutableArray *fetchedObjects = [[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
    [fetchRequest release];
    return [fetchedObjects autorelease];
}

这是我正在使用的示例代码,即使 View2 具有相同的回调并遵循相同的流程。

编辑 1 前面忘了提这个,我总是在 saveToCoreData 方法中得到错误。另外,要注意的另一件事是,如果我删除代码以删除对象,则一切正常(我需要在保存更新的数据之前从表中删除所有现有数据)。不知道发生了什么。

【问题讨论】:

    标签: iphone objective-c core-data fault


    【解决方案1】:

    您在 readFromCoreData 方法中过度释放 fetchedObjects。无论如何,executeFetchRequest 都会返回给您自动释放的对象。当当前运行循环完成执行时(当您从视图中跳转时),它会尝试释放对象两次(假设您没有使用自己的自动释放池)。

    我会改变

    return [fetchedObjects autorelease]; 
    

    return fetchedObjects;
    

    【讨论】:

    • 我只是重新阅读了您的问题,也许我的建议(这对您来说是个问题)不是您具体错误的完整答案。我错过了你得到 NSObjectInaccessibleException 并假设你得到一个 EXC_BAD_ACCESS。
    • Damien,感谢您的快速回复。你是对的,我不应该自动释放 fetchedObjects。我纠正了它。我之前忘了提到这一点,它在 saveToCOreData 方法中总是失败。如果我删除保存选项,应用程序运行良好。
    • @Naz Hussain:一切都是从同一个线程完成的吗?尤其是您从 HTTP 代码中获得的回调?
    • 不,每个 HTTP 请求都是不同的线程,我为每个线程使用不同的 managedObjectContexts。
    • 您是否曾经在线程之间传递 nsmanagedobjects?如果是这样,您是否使用对象 ID?特别是你在主线程上与 UIKit 交互的地方?
    【解决方案2】:

    删除您的删除代码使其工作的原因是因为您正在删除持久存储中的数据,而没有更新仍然在内存中具有与该数据相关联的托管对象实例的其他视图。请记住,虽然 Core Data 处理对象,但每个对象必须在其后面的数据库中有一行。当您删除该行时,Core Data 会生气。

    因此,要解决此问题并仍然删除您的数据,您应该让您的视图监听NSManagedObjectContextWillSaveNotification 和/或NSManagedObjectContextDidSaveNotification 通知,并使用您商店中最新版本的数据更新您的视图。此时您应该丢弃视图所持有的所有 Core Data 对象,并从存储中重新加载它们。

    【讨论】:

    • casademora,感谢您的详细回复。将实施通知。再次非常感谢。
    • 感谢 Casademora,我现在正在收听通知,似乎没有崩溃。感谢您的帮助。
    【解决方案3】:

    关于信息,昨天,我遇到了同样的错误。我签入了该应用程序的实时版本,它仍然存在。哎呀。

    我遍历了将信息添加到核心数据堆栈的所有排列,直到崩溃发生。

    然后,我使用 SqliteManager 从模拟器库中的应用程序中查看了 sqlite 文件。我在一个表中发现了一个数据错误。发生这种情况是因为第一次运行应用程序时使用了一个启动器数据库。错误出现在启动数据库中。

    再次运行应用程序,测试每个表中的每个字段。又发现了好几处。我记得读过这个问题,并认为也许其他人可以从我的错误中受益。

    【讨论】:

      【解决方案4】:

      我刚刚在我的代码中解决了这个错误。似乎我的缓存以某种方式损坏了。我使用了 Christopher Pickslay 和 Keil Gillard 的删除或重命名缓存的建议,瞧,崩溃解决了。 NSFetchedResultsController index beyond bounds

      【讨论】:

      • 这个解决方案为我做到了!我的缓存被命名为“Master”。将其更改为另一个名称后,它就像魅力一样。谢谢你。比许多事件处理简单得多
      猜你喜欢
      • 2012-08-07
      • 2015-02-03
      • 1970-01-01
      • 2012-12-27
      • 2014-12-04
      • 1970-01-01
      • 1970-01-01
      • 2014-11-21
      • 2011-10-21
      相关资源
      最近更新 更多