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

NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSPrivateConcurrencyType];
[childContext setParentContext: _mainContext];

另外,当单击按钮时,我保存上下文:(稍微复杂一点,但遵循此结构)
[childContext performBlock:^{
    [childContext save:nil];
    [_mainContext save:nil];
}];

单击两次或两次以上(不确定是否取决于总点击次数)后,数组中的按钮对象变为fault

根据文档:访问故障对象的属性应加载持久对象。
即使当我访问NSManagedObject的属性时,该对象仍然是故障,属性是nil

为什么对象在我的阵列中发生故障?如何访问故障对象的属性?

编辑:

加载UIViewController时,我正在从数据存储区中获取所有现有对象:
-(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中的NSArray来填充NSMutableArray。

创建一个新的Person对象:
-(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或其他内容)。

最佳答案

NSManagedObject与创建它们的NSManagedObjectContext保持紧密的关系。造成这种情况的特定原因是,受管对象始终是可变的,因此可能需要写回存储,并且有可能会发生将来的错误-Core Data可能会明确选择不将整个持久性存储加载到内存中,但可能必须处理将来随便遍历对象图或内存不足警告。

(此外:这也是为什么最不能使用Core Data对象的原因除了创建它们的线程/队列之外,不能在其他任何对象上使用它;这是上下文以及上下文与对象之间隐式通信的各种方式所没有的。'' t安全)

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

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

因此,您通常要做的是在对象创建时仍处于事件状态的对象上调用objectID。然后,您可以将其传递给其他任何想要的人。然后,他们将使用[myManagedObjectContext -existingObjectWithID:error:]获取可以安全使用的托管对象的新副本。新副本将绑定(bind)到该上下文而不是原始副本,因此无论何时何地该上下文都是安全的,而不是原始副本将是安全的。

唯一可能的意外是,当您第一次插入对象时,它仅获得一个临时对象ID。这是因为Core Data希望将需要插入存储中的东西分批处理,然后仅在您请求保存时才一次将它们全部插入。

出于您的目的,您始终不希望在保存之前传递ID,因为该对象在父存储区中将不存在。因此,这点在某种程度上是学术性的,但是假设您出于其他原因想要隐藏ID,则还可以考虑使用上下文的 -obtainPermanentIDsForObjects:error: ,它可以比实际保存的速度快很多,具体取决于您的商店类型,并且绝对不会慢一点。

关于ios - NSManagedObject保持故障,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14738726/

10-13 03:48