Speichern in CoreData-Rahmen auf hintergrund-thread
Bin ich zu kämpfen mit diesem für einige Zeit jetzt und die Dokumentation von Apple und SO nicht helfen, so weit. Ich war mit ManagedObjectContext auf eine UIManagedDocument und der code unten funktioniert gut. Ich habe mich dann entschlossen mit der Apple-Vorlage für CoreData in AppDelegate, so-Modell, persistent store coordinator und dem Kontext erstellt, in AppDelegate. Abrufen mit AppDelegate Kontext ist kein problem, aber speichern im hintergrund ist ein Problem. Ich sollte den lokalen Kontext, auf den thread bin ich sparen und als pro Apple, um den gleichen Beharrlichkeit store-Koordinator. Aber der code unten nicht tatsächlich die Daten zu speichern. Kann hier mal jemand bitte beraten? Danke.
- (void)fetchAndPersist
{
dispatch_queue_t ffetchQ = dispatch_queue_create("ForFetch", NULL);
dispatch_async(ffetchQ, ^{
NSManagedObjectContext *secureManagedObjectContext;
NSPersistentStoreCoordinator *coordinator = [appDelegate persistentStoreCoordinator];
if (coordinator != nil) {
secureManagedObjectContext = [[NSManagedObjectContext alloc] init];
[secureManagedObjectContext setPersistentStoreCoordinator:coordinator];
}
//find missing date
DataManager *dataManager = [[DataManager alloc] init];
NSDate *missingDate = [dataManager findMissingDateFromDate:selectedDate inContext:secureManagedObjectContext];
if (missingDate) {
//fetch and parse data
DataFetcher *dataFetcher = [[dataFetcher alloc] init];
NSDictionary *fetchResponse = [dataFetcher parseDataForDate:missingDate];
//persist it in a block and wait for it
[secureManagedObjectContext performBlock:^{
DataStore *dataStore = [[DataStore alloc] init];
BOOL parsingError = [dataStore persistData:fetchResponse inContext:secureManagedObjectContext];
if (parsingError) {
//handle error
} else {
dispatch_async(dispatch_get_main_queue(), ^{
//perform on main
[self fetchAndPersist];
});
}
}];
}
});
}
- Warum sparen in einem anderen thread ? Ist es wirklich notwendig, für das, was Sie tun in diesem Fall ?
- Wenn du meinst mit 'speichern in einem anderen thread" die performBlock Betrieb, dann ist es auch nicht. Alles was ich brauche ist die einfachste Holen und weiterhin den Betrieb der geht außerhalb der Haupt-thread.
- Um zu klären, derzeit wird der code mit crash-report 'Kann nur nutzen -performBlock: auf einem NSManagedObjectContext, die erstellt wurde, mit einer Warteschlange.' Wenn ich kommentiere die performBlock Zeile, der code läuft in endlos-Schleife, also der Haupt-thread nicht sehen, die Daten, die gespeichert worden ist.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Versuchen, verwenden Eltern /Kind-Kontexte:
http://www.cocoanetics.com/2012/07/multi-context-coredata/
In dem oben genannten link finden Sie ein Codebeispiel.
Ihrem Absturz tritt auf, weil Ihr
NSManagedObjectContext
ist die ältere, veralteter thread confinement-Modell für die Kern-Daten-Parallelität:secureManagedObjectContext = [[NSManagedObjectContext alloc] init];
init
ist nur ein wrapper uminitWithConcurrencyType:
mit dem argumentNSConfinementConcurrencyType
. Dies schafft den Kontext mit dem thread confinement-Modell, die nicht verwenden könnenperformBlock:
oderperformBlockAndWait:
. Nur zusammenhängen mit der neueren (nicht überholt!) queue-confinement-Modell können diese Methoden verwenden, und nutzen diese Methoden für den Zugriff auf den Kontext oder Objekte, die zu es. Einen Kontext schaffen, mit Warteschlange der Entbindung und eine private Warteschlange:secureManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
Wenn Ihr code migriert wurde, um mit einer privaten Warteschlange Kontext könnte man auch entfernen Sie Ihre serielle dispatch queue, wie die private Warteschlange Kontext eine entsprechende Funktionalität bietet.