Kerndatenmuster: Wie können lokale Informationen bei Änderungen im Netzwerk effizient aktualisiert werden?

Ich habe einige Ineffizienzen in meiner App, die ich verstehen und beheben möchte.

Mein Algorithmus ist:

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

Ich überprüfe die Zeilen A und B, indem ich eine Prädikatabfrage mit dem Schlüssel des betreffenden Objekts erstelle, der Teil meines Schemas ist. Ich sehe, dass sowohl A (immer) als auch B (wenn die Ausführung in diesen Teil verzweigt ist) eine SQL-Auswahl wie folgt erzeugen:

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.0071s für eine Abfrage sind auf einem 3GS-Gerät in Ordnung, aber wenn Sie 100 davon addieren, haben Sie gerade einen 700ms-Blocker.

In meinem Code benutze ich einen Helfer, um diese Abfragen durchzuführen:

- (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
}

Ich denke, das ist falsch und ich sollte die Überprüfung auf eine andere Weise durchführen. Es sollte die Datenbank nur einmal treffen und danach aus dem Speicher kommen, richtig? (Die SQL wird auch für Objekte ausgeführt, von denen ich sicher bin, dass sie lokal vorhanden sind und mit vorherigen Abfragen in den Speicher geladen werden sollten.) Wenn ich jedoch nur myObjectId von einer externen Quelle habe, ist dies das Beste, was ich mir vorstellen kann.

Vielleicht lautet die Frage also: Wenn ich myObjectId (eine Core Data int64-Eigenschaft in MyObject) habe, wie soll ich dann korrekt prüfen, ob das betreffende lokale Objekt im CD-Speicher vorhanden ist oder nicht? Laden Sie den gesamten Satz möglicher Übereinstimmungen vor und prädizieren Sie dann ein lokales Array?

(Eine mögliche Lösung besteht darin, dies in einen Hintergrundthread zu verschieben. Dies ist in Ordnung, außer wenn ich die Änderungen vom Thread erhalte und [moc mergeChangesFromContextDidSaveNotification: aNotification] ausführe (geänderte Objekte vom Hintergrundthread durch Benachrichtigung erhalten).) blockiert noch.)

Antworten auf die Frage(6)

Ihre Antwort auf die Frage