2013-04-12 8 views
6

Ich habe schon einige Stunden auf diesem einen verbracht und ich kann nicht scheinen, eine Lösung zu finden. Zunächst einige Spezifikationen von dem, was ich habe:Core Data Inkonsistenz - holen manchmal liefert nichts zurück

  • Objective-C iOS 6 App mit Core Data
  • Core Data wird von UIManagedDocument initialisiert, die das automatische Speichern gedreht hat auf
  • ManagedContext von UIManagedDocument gespeichert in einer statischen Variable und in der gesamten App wiederverwendet
  • Die App verwendet RestKit und ich verwende ActiveRecord Kategorie, die es bietet.

Ich habe ein Modell mit Team Entität. In der App gibt es einen Team List View Controller, der die Teams aus dem Backend lädt. Das Backend gibt das JSON-Array zurück, das unter anderem die Team-ID enthält. Ich speichere diese ID im Feld "id" in meinem Modell und während ich über die Serverantwort iteriere, suche ich nach, ob das Team für die angegebene ID bereits existiert. Wenn dies der Fall ist, aktualisiere ich nur seine Informationen und gebe das Objekt weiter, wenn nicht - ich erstelle es zuerst.

Und hier wird es bizarr. Das funktioniert 90% der Zeit. Ich kann den Team List-Controller laden, in der App weiter gehen, zurück zum Controller (der die Daten erneut lädt) und es ist die meiste Zeit in Ordnung. Hin und wieder gibt meine Abrufanforderung nichts zurück. Wie in:

NSArray *results = [context executeFetchRequest:request error:&error]; 

wird leeren Array zurückgeben, und der Fehler ist ebenfalls leer. Nichts auf dem Server ändert sich ständig. Die Anforderung, wenn ich versuche, es zu debuggen, sieht wie folgt aus:

<NSFetchRequest: 0x127a0e20> (entity: Team; predicate: (id == "123"); sortDescriptors: ((null)); limit: 1; type: NSManagedObjectResultType;) 

Als ich das SQLite-Store in einem externen App Vorschau kann ich für diese ID das Team Artikel sehen, dass vorhanden ist, und in anderem 90% mal wird es tatsächlich geladen. Was ist noch bizarrer, als ich SQLDebug gedreht habe auf die ich sehen kann:

2013-04-12 12:00:27.934 SportLink[10831:c07] CoreData: annotation: fetch using 
NSSQLiteStatement <0x12656d10> on entity 'Team' with sql text 'SELECT 0, t0.Z_PK, 
t0.Z_OPT, t0.ZACI1, t0.ZACI2, t0.ZACI3, t0.ZALTFIRSTNAME, t0.ZALTSECONDNAME, t0.ZCOLOR1, 
t0.ZCOLOR2, t0.ZGENDER, t0.ZICON, t0.ZID, t0.ZLOCATION, t0.ZLOGO1, t0.ZLOGO2, t0.ZNAME, 
t0.ZTYPE, t0.ZSPORT FROM ZTEAM t0 WHERE t0.ZID = ? LIMIT 133' returned 6 rows 

was bedeutet, dass die Sicherungsspeicher tatsächlich die Daten geholt, aber aus irgendeinem Grund hat es nicht entlang passieren. Jetzt:

  • ich alles im Hauptthread mache, so ist dies kein Problem
  • Ich glaube, dass automatische Speicherung ist auch kein Problem, da dies auch passieren kann, wenn ich die App schließen und öffnen wieder mit Daten bereits vorhanden.

Irgendwelche Ideen was auf der Erde hier vor sich geht?

Edit: Ich habe die App mit Instrumenten profiliert. Ich trat gerade in den problematischen VC ein, trat dann in den Kinderregler ein und ging, wiederholte dies einige Male, bis sich das Problem manifestierte. Hier sind die Ergebnisse. Vielleicht wird es einfacher sein zu wissen, was hier vor sich geht:

Instruments output

+0

Wann feuern Sie die Anfrage in Ihrem 'TeamListVC'? Was machst du, wenn die Ergebnisse geladen wurden? Sie können zusätzlich '[result count]' nach Ihrer Anfrage protokollieren, um ein bisschen mehr zu verfolgen. – flashfabrixx

+0

versuchen, die stalenessInterval des Hauptkontextes auf 0 –

+0

@DanShelly setzen leider hat das nicht geholfen. – mav

Antwort

5

Nach wenigen Tagen der Untersuchung habe ich endlich die Ursache für diesen Fehler gefunden. Der Code, der Team-Einheit wurde Holen sah wie folgt aus:

Team *team = [Team findFirstByAttribute:WSK_ID withValue:data[WSK_ID] inContext:moc]; 

WSK_ID nur für @"id" definieren ist.data ist ein Wörterbuch, das ich von RestKit aus einer JSON-Antwort erhalten habe. Da es nicht in einen beliebigen Typ umgewandelt wurde, war es wahrscheinlich ein NSString, während die id Eigenschaft der Team-Entität NSNumber erwartete. Ich weiß zwar nicht, was manchmal fehlgeschlagen ist, ändere dieses Bit jedoch in:

Team *team = [Team findFirstByAttribute:WSK_ID withValue:@([data[WSK_ID] intValue]) inContext:moc]; 

I.e. Die ID-Zeichenfolge wurde in int umgewandelt, und dann wurde das Problem mit NSNumber behoben.

+0

Sqlite3 auf iOS ist absolut schrecklich, wenn es um Interop, Typkonvertierung, etc. kommt - ob Sie CoreData verwenden oder nicht. Meiner Erfahrung nach ist CoreData zwar in einfachen Szenarien hilfreich, erhöht jedoch die Komplexität, indem bestimmte Daten versteckt werden. – Brandon