使用Core Data时的模型实例化问题

时间:2009-08-04 01:08:54

标签: iphone objective-c cocoa cocoa-touch core-data

我对Core Data的一个方面感到有些困惑。也就是说,何时使用基本的alloc / init例程来创建一个包含核心数据的对象并将其保存到当前的托管对象上下文中。

我知道这是一个相当含糊的问题,所以让我举个例子。

我有一个我正在处理的应用程序,它遍历iPhone上所有用户的联系簿。从那里,我写了一个名为'Person'的模型类。我曾经在一群人中做过类似的事情:

Person * person = [[Person alloc] initWithWrapper:mywrapper];

mywrapper将包含一个带有person属性的NSDictionary。稍后我可以使用person对象在我的应用程序中填充地址簿。

现在我开始使用Core Data重建部分应用程序。我是否继续使用上述策略来填充我的地址簿?或者我会做这样的事情:

    Person *person = (Person *)[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:managedObjectContext];

    [person setName:name];
    [person setDob:dob];

    // Commit the change.
    NSError *error;
    if (![managedObjectContext save:&error]) {
        // Handle the error.
    }

问题是,每次应用程序启动时都会执行此代码。我应该不使用核心数据,因为每次应用加载时,它都会使用冗余的人员实例填充存储机制吗?我应该修改我的NSManagedObject(Person类)并添加我的initWithWrapper:方法并继续像往常一样吗?

有点困惑,希望澄清。

2 个答案:

答案 0 :(得分:4)

您永远不应该在托管对象上下文之外初始化Core Data对象 - 根本没有意义。有一些

Person *person = [[[Person alloc] init] autorelease];

你没有好处,因为你不能保存对象,操纵它,或者真正做任何有用的核心数据,而没有上下文(以及模型和商店协调员)备份它。

当您第一次将对象插入Core Data时,您应该只使用alloc - init组合;这就是initWithEntity:insertIntoManagedObjectContext:方法的用途。你是对的,每次你调用那个方法时你都会在Core Data上下文中插入一个新对象并因此存储,如果你不小心的话,你可能会结束重复的对象。

如果您在每次启动时运行代码,我会建议您使用Core Data查询来返回一些现有的Person对象,并且只添加对象(使用初始化方法)在商店里还没有。如果对象已存在,请修改它而不是创建新对象。

诀窍是让这样的东西正常运行。您不应该为iPhone通讯录中的每个联系人执行核心数据提取;像这样的许多小件非常昂贵。理论上你可以获得两个NSSets - 一个Person对象和一个联系人 - 然后通过一些唯一的密钥(比如联系人的名字和姓氏的哈希)来比较它们。我把优化留给你。

关键在于:不要在Core Data对象上使用allocinit,除非您是第一次将该对象插入上下文 。而是查看现有对象并在必要时进行修改。

答案 1 :(得分:0)

是的,最简单的方法是将initWithWrapper方法添加到Person类中。它会是这样的:

- (id) initWithWrapper:(NSDictionary *)wrapper {
  NSEntityDescription * person = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:someMOC];
  if (self = [super initWithEntity:person insertIntoManagedObjectContext:someMOC]) {
    //do your wrapperly initialization here
  }
  return self;
}

唯一的缺点是这个方法必须知道它应该将对象插入哪个managedObjectContext,所以你必须找到一种方法来提供它。

话虽这么说,我一直都在使用这种模式。