Récupération en arrière-plan des données de base via le nouveau NSPrivateQueueConcurrencyType

Est-ce vraiment si simple maintenant dans iOS5?

J’avais l’habitude d’effectuer une récupération en arrière-plan en utilisant ce code dans mon AppDelegate:

dispatch_queue_t downloadQueue = dispatch_queue_create("DownloadQueue", NULL); dispatch_async(downloadQueue, ^{ self.myDownloadClass = [[MyDownloadClass alloc]initInManagedObjectContext:self.managedObjectContext]; [self.myDownloadClass download]; }); dispatch_release(downloadQueue); 

Ma classe de téléchargement effectue une NSURLConnection pour récupérer des données XML, utilise NSXMLParser pour parsingr les données, puis met à jour un schéma complexe dans les données de base. Je voudrais toujours passer au thread principal pour réellement mettre à jour les données de base. Code Messy, avec beaucoup d’appels à dispatch_sync (dispatch_get_main_queue () ….

Mon nouveau code ressemble à ceci:

 NSManagedObjectContext *child = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [child setParentContext:self.managedObjectContext]; [child performBlock:^{ self.myDownloadClass = [[MyDownloadClass alloc]initInManagedObjectContext:child]; [self.myDownloadClass download]; }]; 

avec un petit changement à un autre code dans mon AppDelegate pour définir le type de contexte d’object de modèle parent à NSMainQueueConcurrencyType:

 - (NSManagedObjectContext *)managedObjectContext { if (__managedObjectContext != nil) { return __managedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { __managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; [__managedObjectContext setPersistentStoreCoordinator:coordinator]; } return __managedObjectContext; } 

Cela semble fonctionner très bien. L’ensemble du processus de mise à jour s’exécute toujours dans un thread séparé, mais je n’ai pas eu à créer de thread. Cela semble magique.

Rappelez-vous simplement si vous souhaitez valider vos modifications dans les fichiers de données de base physiques, vous disposez également de la fonction d’appel: sur le contexte parent.

Je n’ai pas vraiment posé de question ici. Je poste ceci pour que cela aide les autres car tout ce que j’ai trouvé lors de la recherche des nouvelles méthodes de contexte d’objects gérés iOS5 ne donnait que des détails de haut niveau sans exemples de code. , et discuter de la façon de le faire avant iOS5.

Oui, c’est vraiment aussi simple maintenant (sous iOS 5.0). Pour la compatibilité avec iOS 4, les obstacles précédents restnt, mais la documentation n’est pas trop mauvaise sur le confinement des threads. Peut-être devriez-vous append ceci à une section wiki?

J’essaie de comprendre comment cette nouvelle API est implémentée. Mon schéma habituel pour les données de base multithread est quelque chose comme ceci:

Habituellement dans un NSOperation mais simplifié en utilisant dispatch_async dans cet exemple:

 dispatch_queue_t coredata_queue; // some static queue dispatch_async(coredata_queue, ^() { // get a new context for this thread, based on common persistent coordinator NSManagedObjectContext *context = [[MyModelSingleton model] threadedContext]; // do something expensive NSError *error = nil; BOOL success = [context save:&error]; if (!success) { // the usual. } // callback on mainthread using dispatch_get_main_queue(); }); 

Ensuite, le thread principal répondra en mettant à jour l’interface utilisateur basée sur NSManagedObjectContextDidSaveNotification pour fusionner le contexte principal.

La nouvelle API semble être une enveloppe autour de ce modèle, où le contexte child semble prendre le coordinateur persistant de son parent pour créer un nouveau contexte. Et en spécifiant NSPrivateQueueConcurrencyType sur init, vous vous performBlock que le paramètre performBlock est exécuté dans la queue privée.

La nouvelle API ne semble pas être beaucoup moins codée. Des avantages par rapport aux threads «traditionnels»?