如何在使用嵌套上下文时自动设置Core Data关系 [英] How to automatically setup Core Data relationship when using nested contexts

查看:163
本文介绍了如何在使用嵌套上下文时自动设置Core Data关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在为核心数据中使用嵌套管理对象上下文时出现的问题找出一个合适的解决方案。使用具有两个枚举,即Person和Name的模型,其中每个Person与Name具有一对一的关系,Name的人员关系不是可选的。以前,在Person的 -awakeFromInsert 方法中,我会自动为新的Person创建一个Name实体:

I'm struggling to figure out a decent solution to a problem that arises when using nested Managed Object Contexts in Core Data. Take a model that has two enites, Person and Name, where each Person has a one-to-one relationship with a Name, and Name's person relationship is not optional. Previously, in Person's -awakeFromInsert method, I would automatically create a Name entity for the new Person:

- (void)awakeFromInsert
{
    [super awakeFromInsert];

    NSManagedObjectContext *context = [self managedObjectContext];
    self.name = [NSEntityDescription insertNewObjectForEntityForName:@"Name" inManagedObjectContext:context];
}

这在单个非嵌套管理对象上下文中工作得很好。然而,如果上下文有父上下文,当子上下文被保存时,在父上下文中创建一个新的Person对象,并且在这个新对象上再次调用 -awakeFromInsert 之前原始Person的属性和关系将被复制。因此,创建另一个Name对象,然后在复制现有名称关系时断开连接。保存失败,因为验证浮动名称的now-nil person 关系失败。此问题在此处以及其他地方都有描述。

This works just fine in a single, non-nested managed object context. However if the context has a parent context, when the child context is saved, a new Person object is created in the parent context, and -awakeFromInsert is called again on this new object before the original Person's properties and relationships are copied over. So, another Name object is created, then "disconnected" when the existing name relationship is copied over. The save fails because validation of the floating Name's now-nil person relationship fails. This problem is described here as well as in other places.

到目前为止,我一直无法找到一个很好的解决这个问题的方法。 Lazily在getter方法中创建关系实际上导致同样的问题,因为当新的Person在父上下文中创建时,内部的Core Data机制调用getter。

So far, I've been unable to come up with a good solution to this problem. Lazily creating the relationship in the getter method actually causes the same problem, because the getter is called by internal Core Data machinery when the new Person is created in the parent context.

我唯一能想出的是放弃自动关系生成,并且总是在创建Person的控制器类中创建关系,或者在一个方便的方法中创建关系(例如 + [Person insertNewPersonInManagedObjectContext:] ),它只是由我的代码调用,是始终用于显式创建一个新的Person对象的方法。也许这是最好的解决方案,但我宁愿不必那么严格,只允许一个方法用于创建托管对象,当其他创建方法,我无法控制,其使用我不能容易检查/排除,存在。一方面,它将意味着多个NSArrayController子类,以自定义他们创建托管对象的方式。

The only thing I can come up with is to forgo automatic relationship generation, and always create the relationship explicitly either in the controller class that creates the Person, or in a convenience method (e.g. +[Person insertNewPersonInManagedObjectContext:]) that is only called by my code, and is always the method used to create a new Person object explicitly. Perhaps this is the best solution, but I'd prefer to not have to be so strict about only allowing a single method to be used to create managed objects, when other creation methods that I have no control over and whose use I can't easily check for/exclude, exist. For one thing, it will mean multiple NSArrayController subclasses to customize the way they create managed objects.

任何遇到这个问题的人都想出一个优雅的解决方案,允许一个NSManagedObject在创建/插入时自动创建关系对象?

Has anyone else that has encountered this problem come up with an elegant solution that allows for one NSManagedObject to create a relationship object automatically upon creation/insertion?

推荐答案

我的应用程序中的所有NSManagedObject子类都有一个 + insertInManagedObjectContext:方法。使用该方法,总是 创建这些对象的实例(在我自己的代码中)。在这个方法中,我这样做:

I ended up going with the convenience method solution. All the NSManagedObject subclasses in my app have a +insertInManagedObjectContext: method. Creating instances of those objects (in my own code) is always done using that method. Inside that method, I do this:

+ (instancetype)insertInManagedObjectContext:(NSManagedObjectContext *)moc
{
    MyManagedObject *result = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntityName" inManagedObjectContext:moc]
    [result awakeFromCreation];
    return result;
}

- (void)awakeFromCreation
{
    // Do here what used to be done in -awakeFromInsert.
    // Set up default relationships, etc.
}

NSArrayController问题,解决这不是坏事。我简单地创建了一个NSArrayController的子类,覆盖了 -newObject ,并在我的应用程序中所有相关的NSArrayController使用这个子类:

As for the NSArrayController issue, solving that isn't bad at all. I simply created a subclass of NSArrayController, overrode -newObject, and used that subclass for all the relevant NSArrayControllers in my app:

@implementation ORSManagedObjectsArrayController

- (id)newObject
{
    NSManagedObjectContext *moc = [self managedObjectContext];
    NSEntityDescription *entity = [NSEntityDescription entityForName:[self entityName]
                                              inManagedObjectContext:moc];
    if (!entity) return nil;

    Class class = NSClassFromString([entity managedObjectClassName]);
    return [class insertInManagedObjectContext:moc];
}

@end

这篇关于如何在使用嵌套上下文时自动设置Core Data关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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