在后台线程中使用MagicalRecord和NSXMLParser

问题描述:

我正在使用NSXMLParser来处理需要在我的Core Data模型中结束的大型复杂XML文件。为此,我按照Conway和Hillegass的iOS书籍中讨论的设计模式,在每次到达新节点和新节点动态创建时,更改NSXMLParser的委托。为了创建实体,我在解析期间为每个新节点使用MagicalRecord的MR_createEntity来设置我的数据模型。解析完成后,我致电在后台线程中使用MagicalRecord和NSXMLParser

[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait]; 

将新实体保存到我的Core Data存储中。

这一切工作正常,直到我最近决定将解析移动到后台线程。我注意到XML数据并不总是被导入。所以在谷歌搜索之后,我发现MR_createEntity不应该用于后台线程(链接:https://github.com/magicalpanda/MagicalRecord/issues/298)。

那该怎么办?我看到了两个可能的解决方案:

  1. ,在分析,刚刚创建的所有节点的基础基于结构,NSDictionaries和NSArrays的混合物。这可以在后台线程上完成。一旦完成,我回到主线程并使用MR_importValuesForKeysWithObject或类似的东西将我的数据保存到核心数据中(如此处所述:http://www.cimgf.com/2012/05/29/importing-data-made-easy/)。但是,这将与深嵌套字典和数组的组合工作吗?

    而不是调用MR_CreateEntity
  2. 在解析,我用

    [MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) 
    { 
        MyEntity *entity = [MyEntity MR_createInContext:localContext]; 
    }]; 
    
每次我遇到一个新的节点作为链接Gi​​tHub的上述建议

因此,在我开始切割和修改我的代码之前,要走的路是什么?也许还有另一种方法?

如果我理解正确的MagicalRecord源代码,你只需要一个 saveInBackgroundWithBlock:completion:电话:

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

  • 创建一个临时的背景下,
  • 执行第一在与该上下文相关联的背景队列上阻塞,
  • 个电话MR_saveToPersistentStoreAndWait到临时的上下文保存到 主要方面保存主上下文持久核心,
  • 和最终执行完毕块。
+0

谢谢,我试过上面的代码,我可以看到所有正在执行的代码,但是在完成代码块中,我最终得到了“成功=否,错误= nil”(saveInBackgroundWithBlock已弃用,替换saveWithBlock有完成块中的BOOL和NSError)。所以数据没有保存到商店。我也使用[NSManagedObjectContext MR_contextForCurrentThread]在创建每个实体时获取localContext。也许这是错的? – Koen

+1

@Koen:'saveWithBlock:completion' * should *也适用,但“成功=否,错误=零”很奇怪,我不知道为什么会发生这种情况。但是,我会避免使用'MR_contextForCurrentThread'(比较讨论http://*.com/questions/17814656/passing-a-managedcontext-with-core-date-magical-record)。你应该使用传递给块的'localContext'。 –

+0

我现在通过给所有实体一个上下文属性传递本地上下文以及解析器,现在它工作。仍不确定这是否是最有效的方式(与我原来的问题中的提案1相反)。我会在今天晚些时候或周末之后再看一遍。 – Koen

你试试这个吗? https://*.com/a/13924299/1979953

这样子。

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]; 
}); 

但是,您发现MR_createEntity不应该在后台线程上使用。所以我很困惑。