3

Ich habe Apple-Dokumente gelesen und immer noch gibt es eine Frage, auf die ich keine Antwort finden kann. Ich habe ein UIManagedDocument-Objekt, das zwei verschachtelte Kontexte hat - das untergeordnete in einem Haupt-Thread und ein übergeordnetes in einem privaten Thread. Und als nächstes habe ich eine Serverseite. Wenn die Daten vom Server ankommen, möchte ich sie in mein verwaltetes Dokument in einem Hintergrundthread einfügen.UIManagedDocument verschachtelte Kontexte

Ist es threadsicher, eine asynchrone Warteschlange zu erstellen, dort einen NSManagedObjectContext zu erstellen und den untergeordneten UIManagedDocument-Kontext festzulegen, der in einem Hauptthread erstellt wird?

dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL); 
dispatch_async(fetchQ, ^{ 
    //here goes some code for downloading data from the server 

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    [backgroundContext setParentContext:self.eventDatabase.managedObjectContext]; // is this thread safe? 

    //some code for creating objects in backgroundContext 

    NSLog(@"inserting data in background thread"); 


}); 
dispatch_release(fetchQ); 

Mit anderen Worten - es ist Thread-sicher zu einem Kontext zuzuordnen, die auf einem privaten Thread Eltern erstellt wurden, das wurde auf einem Haupt-Thread erstellt?

Antwort

4

Sie verwenden den privaten Parallelitätstyp. Das heißt, Sie sollten den Code in einer eigenen Warteschlange ausführen (per performBlock). Also, wenn Sie das tun wollen, sollten Sie es so machen ...

NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
backgroundContext.parentContext = self.eventDatabase.managedDocument; 
backgroundContext.performBlock:^{ 
    //here goes some code for downloading data from the server 
    //some code for creating objects in backgroundContext 

    NSLog(@"inserting data in background thread"); 

    // Calling save on the background context will push the changes up to the document. 
    NSError *error = nil; 
    [backgroundContext save:&error]; 

    // Now, the changes will have been pushed into the MOC of the document, but 
    // the auto-save will not have fired. You must make this call to tell the document 
    // that it can save recent changes. 
    [self.eventDatabase updateChangeCount:UIDocumentChangeDone]; 
}); 

Wenn Sie die Warteschlange selbst verwalten möchten, sollten Sie vielleicht eine Entbindung MOC verwenden, sollten Sie mit NSConfinementConcurrencyType init oder mit das Standard-Init, weil das die Standardeinstellung ist. Dann würde es so aussehen ...

dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL); 
dispatch_async(fetchQ, ^{ 
    backgroundContext.parentContext = self.eventDatabase.managedDocument; 

    //here goes some code for downloading data from the server 

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] init]; 

    // Everything else is as in the code above for the private MOC. 
}); 
dispatch_release(fetchQ); 
+0

BTW, vergessen Sie nicht, [backgroundContext save: & error] aufzurufen oder die Änderungen werden nicht in den übergeordneten Kontext verschoben. –

+0

Warum benutzt er nicht einfach das parentContex von UIManagedDocument, dieser Kontext läuft im Hintergrund? –

0

Nein Andrew managedobjectcontext ist nicht Thread-sicher. Um das zu erreichen, was Sie wollen, müssen Sie ein Kind-managedcontext erstellen, Ihre Sachen machen und dann die Änderungen im Kind- und Elternkontext speichern. Denken Sie daran, dass das Speichern nur die Änderungen um eine Stufe erhöht.