将多个条目添加到集合中,同时保留对象链接
我有一个关于在多个表中添加多个 CoreData 条目的问题。
我有以下代码:
while((item = [enumerator nextObject]))
{
DOCategory *cat;
cat = [[self categoryController] getNewCategory];
[cat setName:[item objectForKey: @"name"]];
[cat setDesc:[item objectForKey: @"description"]];
[cat setLastUpdate:updateTime];
//[[self categoryController] commitChanges];
}
我曾经在每次枚举后调用 commitChanges,这可以工作,但需要很长时间,特别是在较旧的设备上,因为初始负载相当大。因此我只想在整个操作结束时保存。
将所有这些反对者添加到 NSSet(或 NSArray)同时保留与 ManagedContext 的链接的最佳方法是什么?通常我会将它们“复制”到集合中,但这在这里不起作用。一个简单的问题,只要有块就可以看到最好的解决方案。
(我假设我不必在创建每个新对象后“提交/保存”,因此结果尚未写入数据库,但可用于搜索,因为过程中存在不同的关系对象)
更新: 经过下面的建议和更多测试后,在我看来,当我没有保存/提交上下文时,它不包含 NSFetchResultController。这是正确的并且应该是这样吗?有没有办法在“缓存”中执行所有操作(包括搜索以创建关系),然后在所有操作完成后提交?
更新2: 为了获取托管对象,我在控制器类中有一个过程:
- (DOCategory *) getNewCategory{
return (DOCategory *)[NSEntityDescription insertNewObjectForEntityForName:@"Category" inManagedObjectContext:managedObjectContext];
}
看起来代码运行良好,包括交叉引用,直到我添加使用所有其他托管对象的最终对象。该代码一定有问题。
I have a question regarding the addition of multiple CoreData entries in multiple tables.
I have the following code:
while((item = [enumerator nextObject]))
{
DOCategory *cat;
cat = [[self categoryController] getNewCategory];
[cat setName:[item objectForKey: @"name"]];
[cat setDesc:[item objectForKey: @"description"]];
[cat setLastUpdate:updateTime];
//[[self categoryController] commitChanges];
}
I used to call the commitChanges after each enumeration, and that works, but takes a long time, especially on older devices as the initial load is quite substantial. Therefore I just want to save at the end of the whole operation.
What is the best way to add all those objectors to a NSSet (or NSArray) while preserving the link to the ManagedContext. Normally I would 'copy' them into the set, but that doesn't work here. A simple question, just have a block to seeing the best solution.
(I assume that I don't have to 'commit/save' after every new object I created, so the results are not written to the database yet, but are available for searches as there are different relational objects in the procedure)
Update:
After the suggestion below and more testing, it appears to me that when I haven't saved/committed the context it is not included NSFetchResultController. Is this right and supposed to be the way? Is there a way to do all the operations (including searches to create relations) in 'cache' and then commit once all is done?
Update 2:
In order to get the Managed Object I have a procedure in the Controller-class:
- (DOCategory *) getNewCategory{
return (DOCategory *)[NSEntityDescription insertNewObjectForEntityForName:@"Category" inManagedObjectContext:managedObjectContext];
}
It appears that the code runs fine, including cross references, until I come to adding the final object which uses all the other managed objects. There must be some problem in that code.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的代码是老式 Objective-C 1.0,因此最好更新它。您很少再像这样直接使用枚举器了。
处理此问题的最佳方法是通过使用 +[NSEntityDescription insertNewObjectForEntityForName:inManagedObjectContext:] 将新的托管对象插入到上下文中来创建新的托管对象,这既创建了托管对象,又让上下文意识到它。上下文将保留托管对象本身。这就是“托管对象”中“托管”的由来。
进行大量更改时的正常做法是更改所有对象,然后仅在完成所有更改后保存上下文。
更新:
听起来您可能在数据模型本身中正确设置关系时遇到问题。在不知道您的数据模型是什么样子的情况下,我无法确定。
我不鼓励使用带有
insertNewObjectForEntityForName:
的强制转换,例如...因为如果您遇到数据模型问题,例如未提供
DOCategory
类的名称>DOCategory 实体,强制转换会掩盖问题。如果没有定义类,该方法将返回通用NSManagedObject
类的实例,或者如果您不小心为实体定义了错误的类,例如MadeUpClassName
而不是DOCategory
那么强制转换将强制运行时将返回的对象视为DOCategory
对象。在代码中,这可能会正常工作。不太确定您遇到什么问题。最佳实践是对所有对象进行所有更改,然后保存上下文,而不是在每次对任何单个对象进行更改后保存。磁盘操作的成本很高。
如果您对上下文的更改没有反映在 NSFetchResultsController (FRC) 中,那么您很可能没有实现更新表视图的 FRC 委托方法(请参阅 FRC 文档)。另一个可能的错误是您意外创建了两个上下文。如果您使用线程,每个线程都有一个单独的上下文(必需的实践),那么您必须将后台上下文与前台上下文合并,然后才能让前台知道后台中所做的更改。
Your code is old school Objective-C 1.0 so it would be best to update it. You seldom use enumerators directly like that anymore.
The best way to handle this is to create the new managed objects by inserting them into the context using
+[NSEntityDescription insertNewObjectForEntityForName:inManagedObjectContext:]
this both creates the managed object and makes the context aware of it. The context will retain the managed object itself. That's were the "managed" of "managed object" comes from.The normal practice when making a lot of changes is to change all the objects and then save the context only when you are done making all the changes.
Update:
That sounds like you might have a problem with the relationship being set properly in the data model itself. I can't say for certain without knowing what your data model looks like.
I discourage the use of cast with
insertNewObjectForEntityForName:
e.g.... because if you have a data model problem, such as not providing the name of the
DOCategory
class for theDOCatergory
entity, the cast will obscure the problem. If there is no class defined the method will return an instance of the genericNSManagedObject
class or if you accidentally define the wrong class for the entity e.g.MadeUpClassName
instead ofDOCategory
then the cast will force the runtime to treat the returned object as aDOCategory
object. That might work fine until way down in the code.Not exactly sure what problem you are seeing. It is best practice to make all changes to all objects and then to save the context instead of saving after every change to any single object. Disk operations are expensive.
If your changes to the context are not reflected in the NSFetchResultsController (FRC) then you most likely did not implement the FRC delegate methods that update the tableview (see FRC docs.) Another possible error is that you've created two context accidentally. If you are using threads, each with a separate context (required practice) then you have to merge the background context with the front context before the changes made in the background are made known to the foreground.