【问题标题】:Core Data: Can't Use Previously Saved Object核心数据:不能使用以前保存的对象
【发布时间】:2010-11-13 00:06:50
【问题描述】:

我真的被这两件事困住了。

我想做什么:

  1. 我的实体很简单。这是一个“记录”。
  2. 它有一个“名称(NSString)”和“父级(relationShip)”
  3. “父”连接到自身,实体“记录”。

好的,现在我要创建“parentRecord”和“simpleRecord”。

我尝试使用该代码:

 groupRecord = (record *)[NSEntityDescription insertNewObjectForEntityForName:@"record" 
                                      inManagedObjectContext:self.managedObjectContext];
 groupRecord.name = GroupTextField.text;
 [self saveContext];

它是“parentRecord”,我将其保存以备将来使用,并捕获在“groupRecord”变量中。

现在我必须创建一个“simpleRecord”。这是一个代码:

record *newRecord = (record *)[NSEntityDescription 
       insertNewObjectForEntityForName:@"record" 
       inManagedObjectContext:self.managedObjectContext]; 
newRecord.name = textField.text;
[newRecord setMyParent:groupRecord]; //and it crashes here!

我重新排列了这段代码,所以 *我没有在“parentRecord”中使用[self saveContext]; *。 只需从变量groupRecord 中使用它。并将其保存在“childRecord”块中。那么一切都很好。记录保存到存储中,我可以从那里读取它。

为什么会这样?如果我想先创建“parentRecord”,保存它,然后 - “childRecord”,我应该怎么做?

为什么我不能使用以前保存的对象? NSManagedObjectContext 是一样的 - 怎么了?

“经典”SQL 我已经足够好了,但 Core Data 正在扼杀我的大脑。

谢谢大家。


更新:

看,saveContext 已经没有崩溃的理由了。这里是:

  1. 创建父实体。
  2. 将其设置为 appDelegate 的变量。
  3. 保存上下文(为父母)。
  4. 创建子实体。
  5. 从 appDelegate 的变量中设置 parentProperty。应用崩溃!

还有:

  1. 创建父实体。
  2. 将其设置为 appDelegate 的变量。
  3. ///////////保存上下文(为父母)。
  4. 创建子实体。
  5. 从 appDelegate 的变量中设置 parentProperty。没有任何崩溃。
  6. 这次保存上下文。
  7. 现在一切都很好。

父属性 - 只是属性的名称。这不是 MOM 文件中父级的一些额外设置。

我想做具有层次结构的实体。 并且没有 Xcode 为我创建的其他方法 - 只是一个属性。

【问题讨论】:

  • 崩溃发生时你会得到什么样的错误信息或堆栈跟踪?
  • @Monochromatique:Warrenm 的建议很重要。你应该遵循它。在不知道什么样的崩溃/错误以及它发生在哪里的情况下,您要求我们花时间进行我们大多数人不会做的疯狂猜测。做好功课。
  • OK...我在网上红了一些信息,做一些尝试..
  • 那么,我现在得到了什么。首先 - 在建立任何关系之前,我必须将任何对象添加到 NSManagedObjectContext。当我创建一个 groupRecord - 我已经保存了它。所以我的 NSManagedObjectContext 变得干净了。并且应用程序在“newChildRecord.myParent = groupRecord”上崩溃了
  • 但是,如果我在前面添加一行 - "[self.managedObjectContext insertObject:groupRecord];"那么一切都很好。嗯...我找到了一个原因,但仍然无法理解 NSManagedObjectContext 的作用。

标签: iphone cocoa core-data nsmanagedobjectcontext


【解决方案1】:

好吧,听起来你有一个简单的数据模型,看起来像这样(伪代码):

Record{
    name:string
    parent-->Record
}

这是危险的,因为没有互惠关系。这可能导致孤立对象并损害对象图的完整性。而是使用:

Record{
    name:string
    parent<--(optional)-->Record.child
    child<--(optional)-->Record.parent
}

现在,您有一个简单的一维链表,例如数组或集合。除了最上面的记录对象外,每个记录对象都有一个父对象,而最下面的对象每个都有一个子对象。要为每个人分配一个,您会这样做:

Record *firstRec; //assuming you have created a custom class for Record
Record *secRec;
firstRec=[NSEntityDescription insertNewObjectForEntityForName:@"Record" 
                                       inManagedObjectContext:self.managedObjectContext];
//-------------------------------------^
secRec=[NSEntityDescription insertNewObjectForEntityForName:@"Record" 
                                       inManagedObjectContext:self.managedObjectContext];
//-------------------------------------^
firstRec.name=someText;
secRec,name=someOtherText;

firstRec.child=secRec;
[self saveContext];

现在,如果您想要一个每个父级可以有多个子级的树形结构,您将拥有一个像这样的对象模型:

Record{
    name:string
    parent<--(optional)-->>Record.child
    child<<--(optional)-->Record.parent
}

然后您的插入和分配更改为:

Record *firstRec;
Record *secRec;
firstRec=[NSEntityDescription insertNewObjectForEntityForName:@"Record" 
                                       inManagedObjectContext:self.managedObjectContext];
//-------------------------------------^
secRec=[NSEntityDescription insertNewObjectForEntityForName:@"Record" 
                                       inManagedObjectContext:self.managedObjectContext];
//-------------------------------------^
firstRec.name=someText;
secRec.name=someOtherText;
[firstRec.addChildObject:secRec];
// or
secRec.parent=firsRec;

[self saveContext];

原因是一对多关系需要一个方法来添加新对象来设置。这不能通过简单的分配来完成。然而,孩子只有一个父母,所以它可以使用简单的作业。由于关系是互惠的,分配给一个对象会自动分配给关系另一端的对象。

它应该是这样工作的。您看到的错误很可能来自错误的对象模型。如果您有一对一的必要关系,如下所示:

Record{
    name:string
    parent<--(required)-->Record.child
    child<--(required)-->Record.parent
}

...如果缺少父母或孩子,您在尝试保存时会遇到问题。同样,如果您尝试将多个对象分配给一对一的关系,您可能会看到您看到的错误。

在进行插入时永远不要使用强制转换,因为如果分配的类和强制转换类不匹配,运行时会强制另一个类进入强制转换,从而导致各种奇怪的错误。

我无法确切地说出您的问题是什么,因为我看不到您的对象模型。但是,这应该为您指明正确的方向。

【讨论】:

  • 我想知道 - 层次结构必须是这种方式吗?
  • 在 SQL(MS、Oracle)的世界里——孩子有父母,这就足够了。访问子记录是 QUERY,父实体处于条件中。但看起来 Core Data 有另一种方式。 parentRecord.Child = (NSSet *) 他的孩子。听起来很花哨。 Core Data 与 RDBMS 有任何关系吗??
  • 天哪,我的巨额帖子似乎无处可去!
  • 如果我想: 1. 创建 parentRecord。将其保存到核心数据。然后创建childRecord。 >> 将 parentRecord 分配给 childRecord.myParent。然后将 childRecord 保存到 Core 数据中。
  • 记录 *firstRec;记录 *secRec; firstRec=[NSEntityDescription insertNewObjectForEntityForName:@"Record" inManagedObjectContext:self.managedObjectContext]; firstRec.name=someText; [自我保存上下文]; //-------------------------------------^ secRec=[NSEntityDescription insertNewObjectForEntityForName:@"Record" inManagedObjectContext:self.managedObjectContext]; //-------------------------------------^ secRec.name=someOtherText;
【解决方案2】:

您愿意分享“saveContext”和“setMyParent”的代码吗?

NSManagedObjectContext 有 -(BOOL)save:(NSError**)error 方法。是在“saveContext”中调用的吗?

而且,如果您的关系被称为“父”,那么您应该使用类似 -addParentObject: ... 的东西来设置关系,这将在您的 Record.h 文件中声明。如果您按特定顺序执行操作,Xcode 将为您执行此操作。否则,您将需要自己编写方法声明。

【讨论】:

    猜你喜欢
    • 2013-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多