首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSManagedObject保持故障

NSManagedObject保持故障
EN

Stack Overflow用户
提问于 2013-02-06 21:02:26
回答 1查看 4.6K关注 0票数 6

假设我有一个类(NSManagedObject的子类)。每次用户单击按钮时,都会创建一个新的Person实例并将其添加到全局NSMutableArray中。另外,新创建的Person实例将被添加到子上下文中,如下所示:

代码语言:javascript
复制
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSPrivateConcurrencyType];
[childContext setParentContext: _mainContext];

另外,当单击按钮时,我保存上下文:(它有点复杂,但遵循以下结构)

代码语言:javascript
复制
[childContext performBlock:^{
    [childContext save:nil];
    [_mainContext save:nil];
}];

在单击两次或更多次(不确定是否取决于单击总数)之后,我的数组中的按钮对象将变成fault

根据docs:访问错误对象的属性应该加载持久对象。

即使在访问NSManagedObject的属性时,对象仍然是错误的,属性是nil

为什么对象在我的数组中是错误的,我如何访问一个错误对象的属性?

编辑

在加载UIViewController时,我从数据存储中获取所有现有对象:

代码语言:javascript
复制
-(NSArray*)fetchPersons {
    NSManagedObjectContext *context = [self managedObjectContext]; //this is _mainContext, it is created with initWithConcurrencyType:NSMainQueueConcurrencyType
    NSFetchRequest  *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *description = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:context];
    [fetchRequest setEntity:description];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"key = %i", aCondition];
    [fetchRequest setPredicate:predicate];
    return [context executeFetchRequest:fetchRequest error:nil];
}

我正在使用来自fetchPersons的这个fetchPersons来填充NSMutableArray。

创建一个新的Person对象:

代码语言:javascript
复制
-(Person*)createPerson {
    NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSPrivateQueueConcurrencyType]; 
    [childContext setParentContext:[self managedObjectContext]];
    Person *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:childContext];
    return person;
} 

我不知道如何用“bjectID`”来处理对象。我使用childContext作为临时上下文。有时我需要一个Person实例,但我不想将它保存到持久存储中(或者在开始时将它插入主上下文)。

经过所有这些步骤之后,我的NSMutableArray中有了所有的对象。在创建一些对象之后,我获得了零属性(故障对象),并尝试记录它们的属性(person.name或其他什么)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-02-07 20:19:45

NSManagedObject与创建它们的NSManagedObjectContext保持着紧密的关系。造成这种情况的具体原因是托管对象总是可变的,因此可能需要写回存储,而且未来可能会出现故障-- Core数据可能显式地选择不将整个持久存储加载到内存中,但可能必须处理对象图的未来任意遍历或内存警告低的问题。

(旁白:这也是核心数据对象除了在线程/队列上创建之外不能使用的最接近的原因;上下文和对象之间的隐式通信是不安全的。)

实际上,这意味着您不应该允许托管对象超过其存储空间。

为了允许您在具有不同上下文的不同代理之间来回发送对象,Apple实现了NSManagedObjectID,它是任何托管对象的唯一标识符。它是一个完全不透明的类,但是作为信息,如果您有一个SQLite存储,那么它就是对相关表和行的引用;如果您有其他存储类型之一,那么它类似地是指向存储中某个位置的指针。它本身不携带任何对象数据。

因此,您通常要做的是在对象创建的上下文仍然存在的情况下,调用对象的objectID。然后你可以把它传递给其他人。然后,他们将使用[myManagedObjectContext -existingObjectWithID:error:]获得一个新的托管对象副本,可以安全地使用。新的副本将绑定到该上下文,而不是原件,因此无论何时和多久,该上下文都是安全的,而不是原件。

唯一可能的惊喜是,当您第一次插入一个对象时,它只获得一个临时的对象ID。这是因为Core数据喜欢对需要插入到存储中的东西进行分批处理,然后只在请求保存时立即将它们全部插入。

出于您的目的,您不希望将ID传递到保存之后,因为对象将不存在于父存储中。因此,这一点在一定程度上是学术性的,但如果您出于其他原因想要查询ID,您还可以考虑使用上下文的-obtainPermanentIDsForObjects:error:,它可以比实际的保存速度快得多,这取决于您的存储类型,而且绝对不会慢。

票数 20
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14738726

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档