Ich habe eine UITableView
, die eine NSFetchedResultsController
als Datenquelle verwendet.
Der Hauptdatenspeicher wird in mehreren Hintergrundthreads aktualisiert, die parallel ausgeführt werden (jeder Thread verwendet sein eigenes NSManagedObjectContext
).
Der Haupt-Thread beobachtet die NSManagedObjectContextDidSaveNotification
Benachrichtigung und aktualisiert seinen Kontext mit mergeChangesFromContextDidSaveNotification:
.
Manchmal passiert es, dass NSFetchedResultsController
ein sendet
NSFetchedResultsChangeUpdate
event mit einem IndexPfad, der nicht existiert
mehr an diesem Punkt.
Zum Beispiel: Die Ergebnismenge des abgerufenen Ergebnis-Controllers enthält 1 Abschnitt mit 4 Objekten. Das erste Objekt wird in einem Thread gelöscht. Das letzte Objekt wird in einem anderen Thread aktualisiert. Dann manchmal die Folgendes passiert:
Aber der abgerufene Ergebnis-Controller enthält jetzt nur noch 3 Objekte und wenn
aufgerufen wird %Vor% zum Aktualisieren der Tabellenansichtszelle gemäß NSFetchedResultsChangeUpdate
Ereignis stürzt dies mit einer NSRangeException
Ausnahme ab.
Danke für jede Hilfe oder Ideen!
Ich habe jetzt eine Lösung für mein Problem gefunden. Im Falle eines Update-Ereignisses muss kein
aufgerufen werden %Vor%, weil das aktualisierte Objekt bereits als anObject -Parameter für den -controller:didChangedObject:...
-Delegaten angegeben wurde.
Ich habe daher -configureCell:atIndexPath:
durch eine -configureCell:withObject:
-Methode ersetzt, die das aktualisierte Objekt direkt verwendet. Dies scheint ohne Probleme zu funktionieren.
Der Code sieht jetzt so aus:
%Vor%Dies ist eigentlich ziemlich häufig wegen des Fehlers in Apples Kesselplattencode für NSFetchedResultsControllerDelegate , die Sie erhalten, wenn Sie ein neues Master- / Detailprojekt mit aktivierten Core Data erstellen:
%Vor%anObject
Warum sollten Sie den abgerufenen Ergebniscontroller abfragen und riskieren, einen falschen Indexpfad zu verwenden, wenn Ihnen das Objekt bereits übergeben wurde? Martin R empfiehlt diese Lösung auch .
Ändern Sie einfach die Hilfsmethode configureCell:atIndexPath:
, indem Sie einen Indexpfad verwenden, um das tatsächlich geänderte Objekt zu übernehmen:
Verwenden Sie in Zelle für Zeile:
%Vor%Schließlich, in der Aktualisierung verwenden:
%Vor%newIndexPath
Ab iOS 7.1 werden sowohl indexPath
als auch newIndexPath
übergeben, wenn ein NSFetchedResultsChangeUpdate auftritt.
Halten Sie einfach die Standardimplementierung von indexPath beim Aufruf von cellForRowAtIndexPath, aber ändern Sie den zweiten Indexpfad, der an newIndexPath gesendet wird:
%Vor%Ole Begemanns Lösung besteht darin, die Indexpfade neu zu laden. Ersetzen Sie den Aufruf zum Konfigurieren der Zelle durch einen Aufruf zum erneuten Laden von Zeilen:
%Vor%Bei dieser Methode gibt es zwei Nachteile:
nil
" zurück, wenn die Zelle nicht sichtbar ist oder indexPath
außerhalb des Bereichs liegt. " Daher wäre es korrekter, dies mit zu überprüfen indexPathsForVisibleRows vor dem Aufruf von Reload-Zeilen. event
ein Titelattribut hinzu. Füllen Sie die Tabelle mit mehreren Datensätzen auf (z. B. in viewDidLoad
führen Sie diesen Code aus)
Ändern Sie die Konfigurationszelle, um das Titelattribut anzuzeigen:
%Vor%Zusätzlich zum Hinzufügen eines Datensatzes, wenn die neue Schaltfläche angetippt wird, aktualisieren Sie das letzte Element (Hinweis: Dies kann vor oder nach dem Erstellen des Elements erfolgen, aber stellen Sie sicher, dass Sie es vor dem Speichern ausführen!):
%Vor%Führen Sie die App aus. Sie sollten fünf Elemente sehen.
Tags und Links core-data nsfetchedresultscontroller