代码之家  ›  专栏  ›  技术社区  ›  Coocoo4Cocoa

使用核心数据时的模型实例化问题

  •  2
  • Coocoo4Cocoa  · 技术社区  · 16 年前

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

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

    我目前正在开发一个应用程序,它可以在iPhone上迭代用户的所有通讯录。从那里,我写了一个名为“人”的模型类。我曾经在一个循环中做过类似的事情:

    person*person=[[person alloc]initwitwrapper:mywrapper];

    MyWrapper将包含一个具有Person属性的nsDictionary。稍后,我就可以用Person对象填充应用程序中的通讯簿了。

    现在我已经开始用核心数据重建应用程序的部分。我是否继续使用上面的策略来填充我的通讯簿?或者我做类似的事情:

        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:method,然后像往常那样继续吗?

    稍有困惑,就想澄清一下。

    2 回复  |  直到 16 年前
        1
  •  4
  •   Tim    16 年前

    您不应该在托管对象上下文之外初始化核心数据对象——这根本没有意义。有一些

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

    如果没有上下文(因此是模型和存储协调器)备份,那么不能保存对象、操作对象或真正执行核心数据所提供的任何有用的操作,这对您有好处吗?

    你应该只使用 alloc - init 第一次将对象插入核心数据时的组合;这是 initWithEntity:insertIntoManagedObjectContext: 方法是。你是对的,每次你调用这个方法,你都会在核心数据上下文中插入一个新的对象,然后存储,如果你不小心的话,你可能会得到重复的对象。

    如果您在每次启动时都运行代码,我建议您使用一个核心数据查询来返回一些现有的Person对象集,并且只添加存储中不存在的对象(使用初始化方法)。如果对象已经存在,请修改它,而不是创建新的对象。

    诀窍是让这样的东西正常运行。你不应该为iPhone通讯簿中的每个联系人都做核心数据提取;像这样的小提取非常昂贵。理论上,你可以得到两个nset——一个是person对象,另一个是contact——然后用一些唯一的键(比如联系人名字和姓氏的散列)来比较它们。我把优化留给你。

    关键是: 不要使用 同种异体 初始化 在核心数据对象上,除非您打算第一次将该对象插入到上下文中 . 相反,查看现有对象并在必要时修改它们。

        2
  •  0
  •   Dave DeLong    16 年前

    是的,向Person类添加initWithWrapper方法是最简单的。应该是这样的:

    - (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中,所以您必须找到一种方法来提供它。

    也就是说,我一直在使用这种模式。