Using MagicalRecord and NSXMLParser in a background thread

耗尽温柔 提交于 2019-12-10 11:55:23

问题


I'm using an NSXMLParser to process a large and complex XML file that needs to end up in my Core Data model. To do this I am following the design pattern as discussed in the iOS book by Conway and Hillegass, where the delegate of the NSXMLParser is changed every time a new node is reached and new nodes are created on the fly. To create the entities, I am using MagicalRecord's MR_createEntity for each new node during the parsing to set up my data model. After the parsing is finished I call

[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait]; 

to save the new entities to my Core Data store.

This all works fine, until I recently decided to move the parsing into a background thread. And I noticed the XML data was not always imported. So after some Googling I found that MR_createEntity should not be used on a background thread (link: https://github.com/magicalpanda/MagicalRecord/issues/298).

So what to do? I see two possible solutions:

  1. During the parsing, just create a Foundation based structure of all the nodes, a mixture of NSDictionaries and NSArrays. This can be done on a background thread. Once done, I go back to the main thread and save my data into Core Data using MR_importValuesForKeysWithObject or something similar (as described here: http://www.cimgf.com/2012/05/29/importing-data-made-easy/). But will that work with combinations of deeply nested dictionaries and arrays?

  2. During the parsing, instead of calling MR_CreateEntity, I use

    [MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext)
    {
        MyEntity *entity = [MyEntity MR_createInContext:localContext];
    }];
    

every time I come upon a new node as suggested in the github link above.

So before I start cutting up and modifying my code, what would be the way to go? Maybe there is another approach?


回答1:


If I understand the MagicalRecord source code correctly, you need only a single saveInBackgroundWithBlock:completion: call:

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) {
      // ... parse XML ...
      // ... create entities with:
      MyEntity *entity = [MyEntity MR_createInContext:localContext];
      // ...
} completion:^{
    NSLog("Import finished");
}];

This

  • creates a temporary background context,
  • executes the first block on the background queue associated with that context,
  • calls MR_saveToPersistentStoreAndWait to save the temporary context to the main context and save the main context to the persistent core,
  • and finally executes the completion block.



回答2:


Do you try this? https://stackoverflow.com/a/13924299/1979953

like this.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  // dispatch_async mean your NSXMLParser in a backgound thread
  MyEntity *entity = [MyEntity MR_createEntity];

  ...

  [[NSManagedObjectContext MR_contextForCurrentThread] saveNestedContexts];
});

but, you found that MR_createEntity should not be used on a background thread. So I'm confused.



来源:https://stackoverflow.com/questions/18543739/using-magicalrecord-and-nsxmlparser-in-a-background-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!