将新对象添加到 CoreData 应用程序时出现问题
Posted
技术标签:
【中文标题】将新对象添加到 CoreData 应用程序时出现问题【英文标题】:Problem while adding new Object to CoreData App 【发布时间】:2010-06-05 16:10:26 【问题描述】:又是一天,又是一个 CoreData 问题……但希望现在是最后一个。
好的,这是我的副本:
我有一份入住一个房间并有偏好的酒店客人名单。一旦准备就绪,用户应该选择一个客人并查看数据,还应该能够添加新客人,选择房间(也由应用程序维护)并选择他们的偏好(用户还可以添加新的偏好)。客人可以没有或有很多偏好。
这就是我目前所拥有的。我创建了 3 个实体: - 带有房间号的房间 - 带有名称的首选项 - 带有名称的 GuestInfo -> 带有这些关系房间(目标房间)和首选项(具有“对多关系”的目标首选项)当您创建托管时,首选项是一个 NSSet对象类。
现在我创建了一个 UITableViewController 来显示所有数据。我还有一个编辑和添加模式。当我添加新客人并填写姓名时,一切正常。但是当我想添加首选项或房间号时,我得到了这个错误:
非法尝试在不同上下文中的对象之间建立关系“房间”
现在,让我感到困惑的是,当我添加客人并只输入姓名时,保存它,返回并编辑它并选择它的首选项和房间号?
我在两个 ViewController 中都有这条线来选择房间或偏好:
[editedObject setValue:selectedRoom forKey:editedFieldKey];
用这个 .h :
NSManagedObject *editedObject;
NSString *editedFieldKey;
NSString *editedFieldName;
同样,它在编辑模式下有效,但在我想添加新对象时无效。
可以肯定的是,这就是我为添加新访客所做的:
- (IBAction)addNewItem
AddViewController *addViewController = [[AddViewController alloc] initWithStyle:UITableViewStyleGrouped];
addViewController.delegate = self;
addViewController.context = _context;
// Create a new managed object context for the new book -- set its persistent store coordinator to the same as that from the fetched results controller's context.
NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] init];
self.addingManagedObjectContext = addingContext;
[addingContext release];
[addingManagedObjectContext setPersistentStoreCoordinator:[[_fetchedResultsController managedObjectContext] persistentStoreCoordinator]];
GuestInfo *info = (GuestInfo *)[NSEntityDescription insertNewObjectForEntityForName:@"GuestInfo" inManagedObjectContext:addingContext];
addViewController.info = info;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addViewController];
[self.navigationController presentModalViewController:navController animated:YES];
[addViewController release];
[navController release];
我必须做些什么来初始化 Room 或 Prefs ? 希望有人可以帮助我。谢谢
【问题讨论】:
【参考方案1】:您遇到的问题与您(错误)使用 NSManagedObjectContext 对象密切相关。基本上你不能使用两个不同的托管对象上下文来建立一个由_context 管理的对象和另一个由addContext 管理的对象之间的关系。创建一个新的 NSManagedObjectContext 并将其传递给视图控制器以推送到堆栈上,仅当您要将新对象添加到此上下文时才有效,但如果您要在属于不同 NSManagedObjectContext 对象的对象之间建立关系,则无效。
这就是您收到消息“非法尝试在不同上下文中的对象之间建立关系‘房间’”的原因。要解决此问题,请使用您的 _context 对象创建并保存新对象。
【讨论】:
我刚才写了一个类似的答案。我唯一要补充的是,它可能有助于发帖者在选中 Core Data 选项创建时查看 iPhone/iPad 项目模板。该模板显示了如何在 App 委托中设置核心数据堆栈,并将 NSManagedObjectContext 移交给***(根)视图控制器——然后它可以将其移交给它推送的各种视图控制器。 MOC 应该只创建一次(如您所说)。 +1 感谢您提供的信息,我只是使用 _context 进行了尝试,但这不起作用。目前我实际上只是使用了addingContext,但我不确定为什么,因为这似乎不正确。你能给我更多的细节,我应该如何使用 _context 或发布 addNewItem 的重写?非常感谢 正如马特建议的那样,看一下用于初始化核心数据堆栈并将初始化的上下文正确传递给你的根视图控制器的标准源代码。然后,要添加新项目,创建新项目,分配并初始化添加控制器,最后将上下文和创建的项目传递给新控制器。将控制器放入堆栈并根据需要做出反应:如果用户想要保存项目,则保存它;否则,通过删除它并保存上下文来丢弃您创建的项目。 context 和 item 都是添加控制器的属性。 好吧,我通过 Apple 的 Book CoreData Example 工作,这就是我的代码的来源。我仍然无法找到合适的解决方案。如果我使用“addingContext”我会得到错误,但是如果我重新使用_context,我会在我按下取消前添加一个新项目。任何人都可以告诉我如何避免这种情况? 如果您需要丢弃一个对象,请将其删除并保存上下文。这可以使用诸如 [yourManagedObjectContext deleteObject:yourObject]; 之类的语句来完成。然后,像往常一样保存上下文。【参考方案2】:不要创建新的上下文。您必须使用之前创建房间的相同上下文。为什么每次添加新项目时都要创建新上下文?这就是你得到错误的原因。除非您有线程问题,否则您应该在应用程序启动或加载数据时创建一个上下文,然后在整个过程中使用它。即使存在线程问题,通常每个线程也应该只有一个上下文(或每个临时数据集至少有一个上下文)。
【讨论】:
问题与使用新上下文无关;它与尝试在属于不同上下文的对象之间建立关系有关。每次都创建一个新的上下文是完全可行的,如果您要创建的对象足够简单,这也是标准做法。为什么?因为如果用户改变主意并且不想保存新对象,那么您只需丢弃新创建的上下文即可。无需删除创建的对象。这显示在 Apple 代码中。你所说的关于线程和核心数据的一切都是正确的;-) 我确实理解这个问题,但我无法得到这个问题的实际解决方案。我有一个部分可行的解决方案,允许我添加包括相关详细信息在内的新项目,但如果我按下取消,我会留下一个我不知道如何删除的空记录。 Thx 顺便说一句,如果你没有提到这一点,我根本不会注意到。 要删除您创建的新对象,您需要执行以下操作: [yourManagedObjectContext deleteObject:yourObject];然后,像往常一样保存上下文。以上是关于将新对象添加到 CoreData 应用程序时出现问题的主要内容,如果未能解决你的问题,请参考以下文章
删除 CoreData 对象会导致 EXC_BAD_INSTRUCTION