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その親と同じである必要があります— LibraryBook適切にインスタンス化するには、Libraryの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]戻り値は返されませんnil。したがって、明確にするために、メソッドでmanagedObjectContext作成されたinit場合、インスタンス化後に取得できません。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、コンテキストが割り当て解除されているかどうかが返されます。

2番目 initの関数でもまったく同じことが起こるはずで、テストプログラムでもまったく同じ動作を観察しました。ただし、これは、新しいコンテキストを返すユーティリティ メソッドがどのように呼び出されるかに依存します。

あなたのコード例では、それは呼ばれていnewManagedObjectContextます。で始まるメソッドは保持new...されたオブジェクトを返し、これは init 関数の最後で解放されます。したがって、2 つの機能に違いはないはずです。init

ただし、ユーティリティ メソッドが呼び出されるとgetManagedObjectContext、(大まかに言えば)自動解放されたオブジェクトが返されます。このオブジェクトは、現在の自動解放プールが破棄されるまで、より長く存在する可能性があります。

おそらくこれは、コンテキストがユーティリティ メソッドで作成された場合にコードが機能するように見える理由を説明しています。

結論:後でオブジェクトが必要になった場合に、オブジェクトを作成するためにローカル一時コンテキストを作成しても意味がありません。管理対象オブジェクトはコンテキスト内に存在し、コンテキストが破棄されると、オブジェクトを使用できなくなります。

最初に使用するコンテキストを決定してから、そのコンテキストでオブジェクトとそれらの関係を作成する必要があります。

于 2013-02-05T12:33:39.200 に答える