40 votes

Les Données de base et fils / Grand Central Dispatch

Je suis un débutant avec Grand Central Dispatch (PGCD) et de Base de Données, et j'ai besoin de votre aide pour l'utilisation de Base de Données avec DMC, de sorte que l'INTERFACE utilisateur n'est pas verrouillé alors que j'ai ajouter 40.000 dossiers de Base de Données.

Je sais que le CD n'est pas thread-safe, donc je dois utiliser un autre contexte, puis enregistrer les données et de fusion des contextes, aussi loin que j'ai pu comprendre de certains articles.

Ce que je ne pouvais pas le faire encore, c'est mettre toutes les pièces ensemble.

Donc, dans mon code, j'ai besoin de votre aide pour cela.

J'ai:

/*some other code*/

for (NSDictionary *memberData in arrayWithResult) {

    //get the Activities for this member
    NSArray *arrayWithMemberActivities = [activitiesDict objectForKey:[memberData objectForKey:@"MemberID"]];

    //create the Member, with the NSSet of Activities
    [Members createMemberWithDataFromServer:memberData
                         andActivitiesArray:arrayWithMemberActivities
                              andStaffArray:nil
                           andContactsArray:nil
                     inManagedObjectContext:self.managedObjectContext];
}

Comment puis-je transformer ce travail sur le fond, et ensuite, une fois l'enregistrement effectué, enregistrer les données et de mettre à jour l'INTERFACE utilisateur, sans blocage de l'INTERFACE utilisateur, tout en économisant de l'40.000 objets?

57voto

Rog Points 12427

Voici un bon exemple pour vous d'essayer. Hésitez pas à revenir si vous avez des questions:

self.mainThreadContext... // This is a reference to your main thread context
NSPersistentStoreCoordinator *mainThreadContextStoreCoordinator = [self.mainThreadContext persistentStoreCoordinator];
dispatch_queue_t request_queue = dispatch_queue_create("com.yourapp.DescriptionOfMethod", NULL);
dispatch_async(request_queue, ^{

    // Create a new managed object context
    // Set its persistent store coordinator
    NSManagedObjectContext *newMoc = [[NSManagedObjectContext alloc] init];
    [newMoc setPersistentStoreCoordinator:mainThreadContextStoreCoordinator]];

    // Register for context save changes notification
    NSNotificationCenter *notify = [NSNotificationCenter defaultCenter];
    [notify addObserver:self 
               selector:@selector(mergeChanges:) 
                   name:NSManagedObjectContextDidSaveNotification 
                 object:newMoc];

    // Do the work
    // Your method here
    // Call save on context (this will send a save notification and call the method below)
    BOOL success = [newMoc save:&error];
    if (!success)
        // Deal with error
    [newMoc release];
});
dispatch_release(request_queue);

Et en réponse au contexte de la notification d'enregistrement:

- (void)mergeChanges:(NSNotification*)notification 
{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.mainThreadContext mergeChangesFromContextDidSaveNotification:notification waitUntilDone:YES];
    });
}

Et n'oubliez pas de retirer l'observateur de la notification center une fois que vous avez terminé avec le thread d'arrière-plan contexte.

[[NSNotificationCenter defaultCenter] removeObserver:self];

8voto

bryanmac Points 22834

Voici un extrait de code qui couvre PGCD et de l'INTERFACE utilisateur dans ses termes les plus simples. Vous pouvez remplacer doWork avec votre code qui ne le CoreData travail.

Concernant le CD et le fil de sécurité, une des belles pièces sur le PGCD est que vous pouvez les sections hors des zones de votre application (sous-systèmes) afin de synchroniser et de s'assurer qu'elles sont exécutées sur la même file d'attente. Vous pouvez exécuter toutes les CoreData travail sur une file d'attente nommé com.yourcompany.appname.dataaccess.

Dans l'exemple, il y a un bouton qui appelle la longue course de travail, une étiquette d'état, et j'ai ajouté un curseur pour montrer que je peux déplacer le curseur alors que le bg travail est fait.

// on click of button
- (IBAction)doWork:(id)sender
{
    [[self feedbackLabel] setText:@"Working ..."];
    [[self doWorkButton] setEnabled:NO];

    // async queue for bg work
    // main queue for updating ui on main thread
    dispatch_queue_t queue = dispatch_queue_create("com.sample", 0);
    dispatch_queue_t main = dispatch_get_main_queue();

    //  do the long running work in bg async queue
    // within that, call to update UI on main thread.
    dispatch_async(queue, 
                   ^{ 
                       [self performLongRunningWork]; 
                       dispatch_async(main, ^{ [self workDone]; });
                   });

    // release queues created.
    dispatch_release(queue);    
}

- (void)performLongRunningWork
{
    // simulate 5 seconds of work
    // I added a slider to the form - I can slide it back and forth during the 5 sec.
    sleep(5);
}

- (void)workDone
{
    [[self feedbackLabel] setText:@"Done ..."];
    [[self doWorkButton] setEnabled:YES];
}

3voto

Michael Points 309

Ce blog a une description détaillée de la Base de Données de la simultanéité et de l'exemple de code: http://www.duckrowing.com/2010/03/11/using-core-data-on-multiple-threads/

1voto

plusangel Points 81

Ajout d'une autre source d'info, vous pouvez vérifier

ThreadedCoreData

l'Exemple de Code de l'iOS d'Apple Développeur de la Bibliothèque, qui ont été récemment mis à jour (2013-06-09)

Montre comment utiliser la Base de Données dans un environnement multi-thread, à la suite de la première recommandée motif mentionné dans la Base de Données Guide De Programmation.

Basé sur le SeismicXML de l'échantillon, il télécharge et analyse d'un flux RSS à partir de l'United States Geological Survey (USGS) qui fournit des données sur les récents tremblements de terre partout dans le monde. Ce qui fait de cet échantillon différent c'est qu'il la persistance de magasins de tremblements de terre à l'aide de Données de Base. Chaque fois vous lancez l'application, elle télécharge de nouvelles données sur les séismes, il analyse dans un NSOperation qui vérifie les doublons et les magasins nouvellement créée les tremblements de terre comme des objets gérés.

Pour ceux qui sont nouveaux à la Base de Données, il peut être utile de comparer SeismicXML exemple avec cet exemple et avis les ingrédients nécessaires à la introduire de Base de Données dans votre application.

0voto

Matt S. Points 732

Donc, la réponse sélectionnée pour ce qui est de près de 2 ans maintenant, et il y a un peu de problèmes avec elle:

  1. Ce n'est pas de l'ARC de l'environnement - l'devez supprimer la libération d'appel sur newMoc - ARC ne sera même pas compiler avec qui
  2. Vous devriez faire la weakSelf / strongSelf de la danse à l'intérieur du bloc - sinon, vous êtes probablement la création d'un conserver boucle sur l'observateur de la création. Voir Apple doc est ici: http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithBlocks/WorkingwithBlocks.html
  3. @RyanG demandé dans un commentaire les raisons de son blocage. Ma conjecture est que récemment édité méthode a waitUntilDone:OUI - sauf que cela va bloquer le thread principal. Vous voulez probablement waitUntilDone:NON, mais je ne sais pas si il y a des mises à jour de l'INTERFACE utilisateur de tirer de ces événements de changement ainsi donc, il faudrait tester.

--Edit--

En regardant de plus en #3 - waitUntilDone:OUI n'est pas valide methodSignature pour le contexte de la gestion des objets, alors, comment ce même travail?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X