アプリに非効率性があり、それを理解して修正したいと考えています。
私のアルゴリズムは次のとおりです。
fetch object collection from network
for each object:
if (corresponding locally stored object not found): -- A
create object
if (a nested related object locally not found): -- B
create a related object
スキーマの一部である関連オブジェクトのキーを使用して述語クエリを作成することにより、A 行と B 行をチェックしています。A (常に) と B (実行がその部分に分岐した場合) の両方が、次のような SQL 選択を生成することがわかります。
2010-02-05 01:57:51.092 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE1 t0 WHERE t0.ZID = ?
2010-02-05 01:57:51.097 app[393:207] CoreData: annotation: sql connection fetch time: 0.0046s
2010-02-05 01:57:51.100 app[393:207] CoreData: annotation: total fetch execution time: 0.0074s for 0 rows.
2010-02-05 01:57:51.125 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE2 t0 WHERE t0.ZID = ?
2010-02-05 01:57:51.129 app[393:207] CoreData: annotation: sql connection fetch time: 0.0040s
2010-02-05 01:57:51.132 app[393:207] CoreData: annotation: total fetch execution time: 0.0071s for 0 rows.
クエリの 0.0071 秒は 3GS デバイスでは問題ありませんが、これらを 100 追加すると、700 ミリ秒のブロッカーが得られます。
私のコードでは、これらのフェッチを行うためにヘルパーを使用しています。
- (MyObject *) myObjectById:(NSNumber *)myObjectId {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[self objectEntity]]; // my entity cache
[fetchRequest setPredicate:[self objectPredicateById:objectId]]; // predicate cache
NSError *error = nil;
NSArray *fetchedObjects = [moc executeFetchRequest:fetchRequest error:&error];
if ([fetchedObjects count] == 1) {
[fetchRequest release];
return [fetchedObjects objectAtIndex:0];
}
[fetchRequest release];
return nil;
}
MyObject *obj = [self myObjectById];
if (!obj) {
// [NSEntityDescription insertNewObjectForEntityForName: ... etc
}
これは間違っていると思うので、別の方法でチェックを行う必要があります。データベースに一度だけヒットし、その後はメモリから取得する必要がありますよね? (SQL は、確実にローカルに存在し、以前のクエリでメモリにロードされているはずのオブジェクトに対しても実行されます。) しかし、外部ソースからの myObjectId しか持っていない場合、これは私が考えることができる最高のものです。
したがって、おそらく問題は、myObjectId (MyObject の Core Data int64 プロパティ) がある場合、関連するローカル オブジェクトが CD ストアに存在するかどうかを正しく確認するにはどうすればよいでしょうか? 可能な一致のセット全体をプリロードしてから、ローカル配列を述語しますか?
(考えられる解決策の 1 つは、これをバックグラウンド スレッドに移動することです。スレッドから変更を取得して [moc mergeChangesFromContextDidSaveNotification:aNotification]; を実行する場合を除いて、これは問題ありません (通知によってバックグラウンド スレッドから変更されたオブジェクトを取得する)、これはそれでもブロックします。)