Coredata - “NSObjectInaccessibleException - CoreData 无法完成错误”
我是核心数据的新手,仍在弄清楚具体细节,这个错误已经困扰我几个小时了,我似乎找不到解决方案。非常感谢任何帮助。
问题是这样的,
我有两个视图,它们从服务器获取数据并更新 UI。我已经这样设置了流程
view1 ->从服务器发送 HTTP 请求 - 接收回调 ->将数据保存到 Coredata ->从 Core Data 读取并显示在 UI 上(回调和保存/读取 Coredata 发生在 ViewController 中)
view2 ->从服务器发送 HTTP 请求 - 接收回调 ->将数据保存到 Coredata ->从 Core Data 读取并显示在 UI 上(回调和保存/读取 Coredata 发生在 ViewController 中)
View 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 方法中遇到错误。另外,还要注意的一件事是,如果我删除删除对象的代码,一切都会正常工作(在保存更新的数据之前,我需要从表中删除所有现有数据)。但不确定发生了什么。
I am new to Core data and still figuring out the nuts and bolts and this error has been bugging me for hours and I cant seem to find a solution. Any help is greatly appreciated.
The problem is like this
I have two views which fetch data from the server and Update the UI. I have set up the flow this way
view1 -> Send HTTP Req from Server - Receive Callback -> Save Data To Coredata -> Read From Core Data and display on the UI (callback and saving/reading Coredata happen in ViewController)
view2 -> Send HTTP Req from Server - Receive Callback -> Save Data To Coredata -> Read From Core Data and display on the UI (callback and saving/reading Coredata happen in ViewController)
View 2 repeats this process every 3 seconds as this is a auto refresh screen.
The problem is whenever I try to switch between views 1 and 2 real fast, it crashes the app with above error. If I wait for a few seconds on each view (wait for data to be fetched from the server), it works fine. Am I doing something wrong, what do I need to modify?
- (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];
}
This is the sample code I'm using, even View2 has the same callbacks and follows the same flow.
Edit 1
Forgot to mention this earlier, I always get the error in saveToCoreData method. Also, one more thing to note is that If I remove the code to delete objects it all works fine (I need to remove all the existing data from the table before I save the updated data). Not sure whats happening though.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
删除删除代码使其起作用的原因是,您要删除持久存储中的数据,而无需更新仍具有与内存中该数据相关联的托管对象实例的其他视图。请记住,虽然 Core Data 处理对象,但每个对象后面都必须在数据库中有一行。当您删除该行时,核心数据会生气。
因此,要解决此问题并仍然删除数据,您应该让视图侦听
NSManagedObjectContextWillSaveNotification
和/或NSManagedObjectContextDidSaveNotification
通知,并使用最新的更新您的视图您商店中的数据版本。此时,您应该丢弃视图所持有的任何 Core Data 对象,并从存储中重新加载它们。The reason removing your delete code makes it work is because you are removing the data in the persistent store without updating the other view that still has managed object instances tied to that data still in memory. Remember, while Core Data deals with objects, each object has to have a row in the database behind it. When you delete that row, Core Data gets angry.
So, to fix this problem, and still delete your data, you should have your views listen for
NSManagedObjectContextWillSaveNotification
and/orNSManagedObjectContextDidSaveNotification
notifications and update your views with the most up to date versions of data in your store. It is at this point you should throw away any Core Data objects your views are holding onto, and reload them from the store.我刚刚在我的代码中解决了这个错误。看来我的缓存以某种方式损坏了。我用了 Christopher Pickslay & Keil Gillard 建议删除或重命名我的缓存,瞧,崩溃问题解决了。
NSFetchedResultsController 索引超出范围
I just resolved this error in my code. Seems my cache was corrupted in some way. I used Christopher Pickslay & Keil Gillard's suggestion of deleting or renaming my cache, and voila, crash resolved.
NSFetchedResultsController index beyond bounds
有关信息,昨天,我遇到了同样的错误。我检查了该应用程序的实时版本,它仍然存在。哎呀。
我运行了向核心数据堆栈添加信息的所有排列,直到崩溃发生。
然后,我使用 SqliteManager 查看模拟器库中应用程序中的 sqlite 文件。我发现一张表中存在数据错误。发生这种情况是因为应用程序第一次运行时使用了启动数据库。错误出现在启动数据库中。
再次运行应用程序,测试每个表中的每个字段。又发现了好几处。我记得读过这个问题,并认为也许其他人可以从我的错误中受益。
For info, yesterday, I had the same error. I checked in a live version of the app, and it was still there. yikes.
I ran through all the permutations of adding info to the core data stack until the crash occurred.
I then looked at the sqlite file from the app in the simulator library using SqliteManager. I found a data error in one table. This had occurred as there is a starter db used the first time the app was run. The error was in the starter db.
Ran the app again, testing each field in each table. Found several more occurrences. I remember reading this question, and thought maybe someone else could benefit from my mistake.
您在 readFromCoreData 方法中过度释放了 fetchedObjects 。无论如何,executeFetchRequest 都会返回给您自动释放的对象。当当前运行循环完成执行时(当您从视图跳转时),它会尝试释放对象两次(假设您没有使用自己的自动释放池)。
我会
改为
Your over releasing fetchedObjects in your readFromCoreData method. executeFetchRequest will return to you autoreleased objects anyway. When the current run loop finished executing (when you're jumping from views) then it attempt to release the objects twice (assuming you haven't used your own autorelease pools).
I'd change
to