Guten Abend zusammen,
ich habe im Moment ein Problem mit Core Data und Multi-Threading,
was die App in unregelmäßigen Abständen abstürzen lässt.
Erstmal zum Aufbau der App:
- Suchmaske -> Ergebnisliste -> Detailseite
- Merkzettel
In der Ergebnisliste werden per NSUrlSession die Daten anhand der eingestellten Suchmaske vom Server geladen. Im CompletionBlock werden die geladenen Daten (JSON) in CoreData gespeichert. Wenn ein geladenes Objekt schon in CoreData ist (da zB auf dem Merkzettel) wird dieses Objekt verwendet, ansonsten wird ein neues ManagedObject erstellt.
So ein ManagedObject hat mehrere 1:1 und 1:m Relations.
In der Detailseite werden die kompletten Daten zu dem dem in der Ergebnisliste ausgewählten ManagedObject geladen und im CompletionBlock wird das ManagedObject mit den restlichen Daten gefüllt.
Die Objekte können auf den Merkzettel gelegt werden, dieser soll auch offline verfügbar sein. Daher die Speicherung in CoreData.
Ergebnisliste und Detailseite greifen auf das gleiche Array mit den geladenen Objekten zu.
Ich habe jetzt MagicalRecord eingebaut.
In der Ergebnisliste werden die NSManagedObjects im contextForCurrentThread erstellt und danach mit saveToPersistantStoreAndWait gespeichert.
In der Detailseite werden die restlichen Relationships im managedObject.managedObjectContext erstellt und wiederrum mit saveToPersistantStoreAndWait in die DB gespeichert.
1.
Dadurch dass die Daten async geladen werden und daher im CompletionBlock die ManagedObjects im Background Thread erstellt werden, bekommen diese ManagedObjects auch den Background Context als ManagedObjectContext.
Mit saveToPersistantStoreAndWait werden die Daten in den Main Context gemerged und in die DB gespeichert. Der managedObject.managedObjectContext bleibt aber weiterhin der Background Context?
2.
Wenn ich nun in der Ergebnisliste oder in der Detailseite ein Objekt auf den Merkzettel lege, wird die entsprechende Property auf YES gesetzt. Muss ich dann nach jeder Property Änderung wiederum saveToPersistantStoreAndWait aufrufen? Ansonsten wird diese Änderung wohl nicht in die DB gespeichert?
3.
Im Merkzettel mache ich in viewDidLoad einen FetchRequest auf alle Objekte in der DB, welche die Merkzettel Property auf YES haben. Dies geschieht ja dann im Main Thread = Main Context.
Somit haben die Objecte als ManagedObjectContext den Main Context (welcher in der Ergebnisliste/Detailseite noch der Background Context war).
Wenn ich nun im Merkzettel die Daten eines Objektes vom Server aktualisiere, dann passiert dies ja wieder async im Background Thread (analog zur Detailseite), das Objekt ist aber im Main Context. Dies müsste ja dann auch zu einem Crash führen, da unterschiedliche Contexte. Dann müsste ich wohl das Objekt im Background Context neu fetchen, bearbeiten, speichern. und im Merkzettel den Fetch aller Objekte neu ausführen?
Das sind gerade die ersten Unklarheiten. Ist irgendwie alles eine Wissenschaft für sich^^
Ggf bin ich auch komplett falsch vom Ansatz.
vg
ich habe im Moment ein Problem mit Core Data und Multi-Threading,
was die App in unregelmäßigen Abständen abstürzen lässt.
Erstmal zum Aufbau der App:
- Suchmaske -> Ergebnisliste -> Detailseite
- Merkzettel
In der Ergebnisliste werden per NSUrlSession die Daten anhand der eingestellten Suchmaske vom Server geladen. Im CompletionBlock werden die geladenen Daten (JSON) in CoreData gespeichert. Wenn ein geladenes Objekt schon in CoreData ist (da zB auf dem Merkzettel) wird dieses Objekt verwendet, ansonsten wird ein neues ManagedObject erstellt.
So ein ManagedObject hat mehrere 1:1 und 1:m Relations.
In der Detailseite werden die kompletten Daten zu dem dem in der Ergebnisliste ausgewählten ManagedObject geladen und im CompletionBlock wird das ManagedObject mit den restlichen Daten gefüllt.
Die Objekte können auf den Merkzettel gelegt werden, dieser soll auch offline verfügbar sein. Daher die Speicherung in CoreData.
Ergebnisliste und Detailseite greifen auf das gleiche Array mit den geladenen Objekten zu.
Ich habe jetzt MagicalRecord eingebaut.
In der Ergebnisliste werden die NSManagedObjects im contextForCurrentThread erstellt und danach mit saveToPersistantStoreAndWait gespeichert.
In der Detailseite werden die restlichen Relationships im managedObject.managedObjectContext erstellt und wiederrum mit saveToPersistantStoreAndWait in die DB gespeichert.
1.
Dadurch dass die Daten async geladen werden und daher im CompletionBlock die ManagedObjects im Background Thread erstellt werden, bekommen diese ManagedObjects auch den Background Context als ManagedObjectContext.
Mit saveToPersistantStoreAndWait werden die Daten in den Main Context gemerged und in die DB gespeichert. Der managedObject.managedObjectContext bleibt aber weiterhin der Background Context?
2.
Wenn ich nun in der Ergebnisliste oder in der Detailseite ein Objekt auf den Merkzettel lege, wird die entsprechende Property auf YES gesetzt. Muss ich dann nach jeder Property Änderung wiederum saveToPersistantStoreAndWait aufrufen? Ansonsten wird diese Änderung wohl nicht in die DB gespeichert?
3.
Im Merkzettel mache ich in viewDidLoad einen FetchRequest auf alle Objekte in der DB, welche die Merkzettel Property auf YES haben. Dies geschieht ja dann im Main Thread = Main Context.
Somit haben die Objecte als ManagedObjectContext den Main Context (welcher in der Ergebnisliste/Detailseite noch der Background Context war).
Wenn ich nun im Merkzettel die Daten eines Objektes vom Server aktualisiere, dann passiert dies ja wieder async im Background Thread (analog zur Detailseite), das Objekt ist aber im Main Context. Dies müsste ja dann auch zu einem Crash führen, da unterschiedliche Contexte. Dann müsste ich wohl das Objekt im Background Context neu fetchen, bearbeiten, speichern. und im Merkzettel den Fetch aller Objekte neu ausführen?
Das sind gerade die ersten Unklarheiten. Ist irgendwie alles eine Wissenschaft für sich^^
Ggf bin ich auch komplett falsch vom Ansatz.
vg
Knowing is not enough, we must apply.
Willing is not enough, we must do.
Willing is not enough, we must do.