コード:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"A"
inManagedObjectContext:moc];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"id" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"somePredicate", someObject];
[fetchRequest setPredicate:predicate];
frc = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:moc
sectionNameKeyPath:@"recency"
cacheName:@"frc"];
[fetchRequest release];
frc.delegate = self;
NSError *error;
BOOL success = [frc performFetch:&error];
if (!success) {
NSLog(@"error: %@", error);
}
for (A *a in [frc fetchedObjects]) {
[someMutableArray addObject:a.b];
[someMutableArray addObject:a];
}
データ・モデル:
A と B はエンティティです。A は B に対して必須の対 1 関係を持ちます。B は A に対して逆のオプションの対多関係を持ちます。
上は英語で:
NSFetchedResultsController を初期化して、テーブルビューを強化するデータを取得します。最初のフェッチの後、何らかの処理のためにデータを取っておきます。
さて、後で、私はこれをやろうとします:
id object = [someMutableArray objectAtIndex:someIndex];
NSLog(@"%@", object);
if ([object isMemberOfClass:[B class]]) {
someVar = object.propertyFromB; // problem
} else if ([object isMemberOfClass:[A class]]) {
someVar = object.propertyFromA;
}
質問/問題: 「問題」で示される行がクラッシュします。(編集:解決策については以下を参照してください。ただし、それでも説明が必要です。)
上記の NSLog 呼び出しにより、次の結果が得られます。
2010-01-30 14:47:14.433 app[22618:20b] <B: 0xf7f750> (entity: B; id: 0xf7ba70 <x-coredata://B01FEC86-14D6-4973-BFDB-EDE4AFD24FDC/B/p4> ; data: <fault>)
2010-01-30 14:47:14.438 app[22618:20b] <A: 0xf7e360> (entity: A; id: 0xf35820 <x-coredata://B01FEC86-14D6-4973-BFDB-EDE4AFD24FDC/A/p6> ; data: {
prop1 = value1;
prop2 = value2;
... etc ...
})
つまり、問題のある行によると、オブジェクトがタイプ A の場合、障害が発生しており、メモリで使用できますが、B の場合は障害です。
私の理解では、「問題」行が障害を発生させ、ストアからデータをフェッチする必要がありますが、これは起こっていません。理由を理解し/デバッグしたいと思います。これに willAccessKey/didAccessKey 呼び出しを挿入しようとしました。また、フェッチ要求で setRelationshipKeyPathsForPrefetching:"b" を設定しようとしました。どちらも機能しませんでした。
私の仮説は、NSFetchedRequestController の結果をいくらか悪用しているため、障害のあるエンジンが途中で混乱し、想定されているときに障害をフェッチしないというものです。したがって、適切なタイミングで関連する B オブジェクトをフェッチするために、新しい手動フェッチ リクエストを作成するのが強引な方法だと思います。しかし、より良い方法はありますか?
編集:
問題は、オブジェクト B に私が定義したプロパティ「説明」があったが、それが NSObject の組み込み名と衝突することでした。Xcodeは常に警告を出しましたが、「説明」の内部プロパティ/メソッドは、内部処理ではなく、コンソールなどに文字列をダンプするためにのみ使用されると考えたため、それらを無視しました。
モデルの新しいバージョンを作成し、「説明」の名前を別の名前に変更すると、問題はなくなりました。すべての障害が期待どおりに機能し始めました。
とはいえ、何が起こっているのかわかりません。Core Data は、オブジェクトの「説明」メソッドを使用して内部内省を行っていますか?