NSOperation用于核心数据操作

时间:2017-02-07 19:04:02

标签: objective-c swift core-data nsoperation nsoperationqueue

我的应用程序从某种格式转换为NSManagedObject,因此最好的方法是使用NSOperation(或Swift 3中的Operation)从原始转换数据到NSManagedObject并在完成所有操作后保存该上下文。

我不能为每个Operation使用单独的上下文,因为我的转换器会生成关系(并且只能从相同的上下文访问它们),并且应用程序最多可以运行20次转换,因此它可以使用#39} ;创建新的上下文并在每次转换后保存它并不酷。

所以我需要创建单独的OperationQueue并确保其中的所有操作都是从与上下文相同的线程执行的,我不知道该怎么做。

我只有一个想法:将Operation.main()内的所有内容作为context.perform { }启动,但我并不认为这是一个很好的解决方案。

我找到Regex to strip anything that isn't an html comment,但答案已经过时,我看到接受的答案显然不对。

2 个答案:

答案 0 :(得分:3)

使用您自己的操作队列是最好的方法。使用Core Data,您需要通过modelvar data = from p in product join c in club on p.clubid = c.clubid where c = "Miami Heat" select new PageViewModel { ProducName= p.prodname, ClubName= c.clubname } 使用内置的Core Data并发,然后使用mainQueueConcurrencyTypeprivateQueueConcurrencyType。如您所述使用自定义操作队列将无法正常工作。

这将使用Core Data管理的调度队列。您无法直接计算待处理操作的数量,但您可以使用最终块一次添加一堆块,以完成导入过程完成时需要执行的任何操作。除非您只导入少量数据,否则在导入过程中保存而不是仅在最后保存也是一个好主意,以防止内存使用失控。

答案 1 :(得分:0)

我发现在Operation中使用核心数据的最佳方法是使用privateQueueConcurrencyType生成子上下文,而不需要任何额外的.perform块(已在所需的线程中创建私有操作) )。我对任何其他建议持开放态度。

我已经使用operationQueue.maxConcurrentOperationCount = 1来确保安全性并且没有合并冲突,但我可能会建议这种方法适用于并发操作,但在大多数情况下它将无用,因为操作将在每个其他上下文时等待没合并。

在与waitUntilAllOperationsAreFinished()相同的线程中使用parentContext时要小心,在大多数情况下会导致死锁。

示例代码

class ExampleOperation: Operation {
    let parentContext: NSManagedObjectContext

    init(parentContext: NSManagedObjectContext) {
        self.parentContext = parentContext
        super.init()
    }

    override func main() {
        if self.isCancelled { return }

        let childContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
        childContext.parent = parentContext

        // use here `childContext` context directly
        // e.g.: let result = try childContext.fetch(fetchRequest)

        try? childContext.save()
}