iPhone iOS how to merge Core Data NSManagedObjectContext?

前端 未结 3 1562
挽巷
挽巷 2021-02-04 21:11

I\'m trying to download some JSON objects in the background and am doing quite a bit of multi threading. Once the operation completes, I noticed that this assertion fails:

3条回答
  •  时光取名叫无心
    2021-02-04 21:50

    I really suggest you to read the following link on importing-and-displaying-large-data-sets-in-core-data by Marcus Zarra.

    When you deal with threads, each thread you create needs to have its own context as written in the link which jrturton provided. Then if you want to merge changes between a main context (the one you created in the main thread) and the other context (the one you use in the context), you need to listen for NSManagedObjectContextDidSaveNotification in the main thread

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextHasChanged:) name:NSManagedObjectContextDidSaveNotification object:nil];
    

    and do the merge like

    - (void)contextHasChanged:(NSNotification*)notification
    {
      if ([notification object] == [self mainObjectContext]) return;
    
      if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(contextHasChanged:) withObject:notification waitUntilDone:YES];
        return;
      }
    
      [[self mainObjectContext] mergeChangesFromContextDidSaveNotification:notification];
    }
    

    The notification object contains the changes you made in the thread context.

    Some notes

    Threading is difficult to achieve. The link I provided uses an NSOperation with its context. This is quite simple to set up but since iOS 5 there are some functionalities that make your life easier.

    For example to create a context in a different thread you can do like the following:

    // create a context with a private queue so access happens on a separate thread.
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    // insert this context into the current context hierarchy
    context.parentContext = context;
    // execute the block on the queue of the context
    [context performBlock:^{
    
          // do your stuff (e.g. a long import operation)
    
          // save the context here
          // with parent/child contexts, saving a context pushes the changes out of the current context
          NSError* error = nil;
          [context save:&error];
    }];
    

    In addition you can see the doc for UIManagedDocument. This class integrates well for Core Data and allows you to avoid using the Core Data stack.

    Hope it helps.

提交回复
热议问题