0

我想以简单的方式创建 NSManagedObject 的子类的实例:Library *library = [[Library alloc] init]所以我init像这样覆盖了方法。

- (instancetype)init
{

    NSManagedObjectContext *managedObjectContext = [[NSManagedObjectContext alloc] 
                               initWithConcurrencyType:NSMainQueueConcurrencyType];
    managedObjectContext.parentContext = [RKManagedObjectStore 
                                      defaultStore].mainQueueManagedObjectContext;

   NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Library" 
                                       inManagedObjectContext: managedObjectContext];

   self = [super initWithEntity:entityDescription  
                  insertIntoManagedObjectContext:managedObjectContext];

   return self;
}

在一个视图中,我创建了一个新实例,Library *library = [[Library alloc] init]这工作得很好。现在我需要向与它有关系的对象添加一个Book对象。Library所以一个新的Book实例应该managedObjectContext和它的父实例相同—— Library。要正确实例化Book,我需要获取Library's managedObjectContent:[library managedObjectContent]回馈nil。几个小时后,我有一个解决方法:

- (instancetype)init
{

    NSManagedObjectContext *managedObjectContext = [GTObjectManager newManagedObjectContext];

   NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"City" 
                                       inManagedObjectContext: managedObjectContext];

   self =  [super initWithEntity:entityDescription  
                  insertIntoManagedObjectContext:managedObjectContext];

   return self;
}

在 GTObjectManager 中,我的代码与旧的 init 方法中的代码相同:

+ (NSManagedObjectContext *)newManagedObjectContext
{
    NSManagedObjectContext *managedObjectContext = [[NSManagedObjectContext alloc] 
                               initWithConcurrencyType:NSMainQueueConcurrencyType];
    managedObjectContext.parentContext = [RKManagedObjectStore 
                                      defaultStore].mainQueueManagedObjectContext;
   return managedObjectContext;
}

现在实例化Library *library = [[Library alloc] init]调用[library managedObjectContext]返回 not之后nil。所以澄清一下:如果managedObjectContextinit方法中创建,实例化后我无法得到它。如果在方法managedObjectContent之外创建init,我可以在实例化后得到它。

我无法解释这种行为。它是一种init方法的行为吗?我正在使用 ARC,它是某种 ARC 行为吗?

4

1 回答 1

1

在您的第一个 init函数中,您创建一个本地managedObjectContext对象并使用它来创建托管对象。托管对象不保留其上下文,因此managedObjectContext是对该对象的唯一强引用。ARC 在函数末尾添加代码来释放这个引用,因为它是唯一的引用,所以托管对象上下文被释放。

如果您将以下代码添加到您的init函数(在 之后self = [super initWithEntity:...]),您可以观察到这种行为:

NSLog(@"%@", [self managedObjectContext]);
// Output: <NSManagedObjectContext: 0x100134a00>
managedObjectContext = nil;
NSLog(@"%@", [self managedObjectContext]);
// Output: (null)

如您所见,nil如果上下文已被释放,则向托管对象询问其上下文会返回。

在您的第二个 init函数中,应该会发生完全相同的情况,并且我在测试程序中观察到完全相同的行为。但这取决于如何调用返回新上下文的实用方法。

在您的代码示例中,它被称为newManagedObjectContext. 以 开头的方法new...返回一个保留对象,并在 init 函数结束时释放。init因此,您的两个功能之间应该没有区别。

但是,如果调用了实用方法 eg getManagedObjectContext,那么它会返回(粗略地说)一个自动释放的对象。这个对象可能存在的时间更长,直到当前的自动释放池被销毁。

也许这解释了为什么如果上下文是在实用程序方法中创建的,您的代码似乎可以工作。

结论:如果您以后需要对象,创建本地临时上下文来创建对象是没有意义的。托管对象存在于上下文中,如果上下文被销毁,您将无法再使用这些对象。

您必须首先决定要使用哪个上下文,然后在该上下文中创建对象及其关系。

于 2013-02-05T12:33:39.200 回答