6

私の状況:クラスPerson(NSManagedObjectのサブクラス)があると仮定します。ユーザーがボタンをクリックするたびに、新しいPersonインスタンスが作成され、グローバルNSMutableArrayに追加されます。また、新しく作成されたPersonインスタンスは、次のように子コンテキストに追加されます。

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

また、ボタンをクリックすると、コンテキストが保存されます:(少し複雑ですが、この構造に従います)

[childContext performBlock:^{
    [childContext save:nil];
    [_mainContext save:nil];
}];

2回以上クリックすると(合計クリック数に依存するかどうかはわかりません)、配列内のボタンオブジェクトはになり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];
}

このNSArrayfromを使用しfetchPersonsて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にすべてのオブジェクトが含まれます。いくつかのオブジェクトを作成した後、nilプロパティ(フォールトオブジェクト)を取得し、それらの属性(person.nameまたは何か)をログに記録しようとしました。

4

1 に答える 1

20

NSManagedObjectNSManagedObjectContextは、それらが作成されたとの緊密な関係を維持します。これの具体的な理由は、管理対象オブジェクトは常に可変であるため、ストアに書き戻す必要がある可能性があり、将来障害が発生することが予想されるためです。コア データは、永続ストア全体をメモリにロードしないことを明示的に選択する可能性がありますが、対処する必要がある場合があります。オブジェクトグラフの将来の任意のトラバーサルまたはメモリ不足の警告。

(余談ですが、これは Core Data オブジェクトが作成されたスレッド/キュー以外で使用できない最も近い理由でもあります。安全です)

これが実際に意味することは、管理対象オブジェクトがそのストアよりも長く存続することを許可してはならないということです。

異なるコンテキストを持つ異なるエージェント間でオブジェクトをやり取りできるようにするために、AppleNSManagedObjectIDは管理対象オブジェクトの一意の識別子である を実装しています。これは完全に不透明なクラスですが、参考までに、SQLite ストアがある場合は、関連するテーブルと行への参照です。他の店舗タイプのいずれかを持っている場合、それは同様に店舗内の場所へのポインターです。オブジェクトデータ自体は一切持ちません。

したがって、通常行うことはobjectID、オブジェクトが作成されたコンテキストがまだ生きている間にオブジェクトを呼び出すことです。その後、それを必要な人に渡すことができます。次に、[myManagedObjectContext -existingObjectWithID:error:]を使用して、安全に使用できる管理対象オブジェクトの新しいコピーを取得します。新しいコピーは、元のコンテキストではなくそのコンテキストにバインドされるため、元のコンテキストではなく、そのコンテキストが安全である限りいつでも安全です。

唯一の驚きは、最初にオブジェクトを挿入したときに、一時的なオブジェクト ID しか取得されないことです。これは、Core Data がストアに挿入する必要があるものをまとめて、保存を要求したときにのみ一度にすべて挿入するのが好きだからです。

オブジェクトが親ストアに存在しないため、とにかく保存するまで ID を渡したくありません。したがって、ポイントは部分的に学術的なものですが、他の理由で ID を探し出したい場合は、コンテキストの の使用を検討することも-obtainPermanentIDsForObjects:error:できます。ストアのタイプによっては、実際の保存よりもはるかに高速になる可能性があり、決してそうではありません。もっとゆっくり。

于 2013-02-07T20:19:45.047 に答える