Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 核心数据操作的NSO操作_Objective C_Swift_Core Data_Nsoperation_Nsoperationqueue - Fatal编程技术网

Objective c 核心数据操作的NSO操作

Objective c 核心数据操作的NSO操作,objective-c,swift,core-data,nsoperation,nsoperationqueue,Objective C,Swift,Core Data,Nsoperation,Nsoperationqueue,我的应用程序进行了大量从某种格式到NSManagedObject的转换,所以对我来说最好的方法是使用NSOperation或Swift 3中的Operation将原始数据转换为NSManagedObject,并在所有操作完成后保存该上下文 我不能为每个操作使用单独的上下文,因为我的转换器生成关系,它们只能从同一上下文访问,应用程序可能会运行多达20次转换,所以在每次转换后创建新上下文并保存它并不酷 所以我需要创建单独的OperationQueue,并确保其中的所有操作都是从与上下文相同的线程执行

我的应用程序进行了大量从某种格式到NSManagedObject的转换,所以对我来说最好的方法是使用NSOperation或Swift 3中的Operation将原始数据转换为NSManagedObject,并在所有操作完成后保存该上下文

我不能为每个操作使用单独的上下文,因为我的转换器生成关系,它们只能从同一上下文访问,应用程序可能会运行多达20次转换,所以在每次转换后创建新上下文并保存它并不酷

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

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


我已经找到了答案,但答案已经过时,我发现接受的答案显然不正确。

使用自己的操作队列不是最好的方法。对于核心数据,您需要通过mainQueueConcurrencyType或privateQueueConcurrencyType使用内置的核心数据并发,然后使用perform或performAndWait。使用您描述的自定义操作队列将无法正常工作


这将使用核心数据管理的调度队列。您无法直接获得挂起操作的数量,但可以一次添加一组块,最后一个块在导入过程完成时执行任何需要执行的操作。最好在导入过程中保存,而不是只在最后保存,以防止内存使用失控,除非您只导入少量数据

使用自己的操作队列不是最好的方法。对于核心数据,您需要通过mainQueueConcurrencyType或privateQueueConcurrencyType使用内置的核心数据并发,然后使用perform或performAndWait。使用您描述的自定义操作队列将无法正常工作


这将使用核心数据管理的调度队列。您无法直接获得挂起操作的数量,但可以一次添加一组块,最后一个块在导入过程完成时执行任何需要执行的操作。最好在导入过程中保存,而不是只在最后保存,以防止内存使用失控,除非您只导入少量数据

我发现在操作中使用核心数据的最佳方法是使用privateQueueConcurrencyType创建子上下文,而不需要任何额外的。执行已在所需线程中创建私有操作的块。我愿意接受任何其他建议

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

在使用与parentContext在同一线程中定义的WaitUntillalOperations时要小心,在大多数情况下,这会导致死锁

示例代码
我发现在操作中使用核心数据的最好方法是使用privateQueueConcurrencyType创建子上下文,而不需要任何额外的。执行在所需线程中已经创建了私有操作的块。我愿意接受任何其他建议

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

在使用与parentContext在同一线程中定义的WaitUntillalOperations时要小心,在大多数情况下,这会导致死锁

示例代码
你看到这个答案了吗@danh,是的,但据我所知,NSManagedContext没有用于挂起操作的计数器,我如何知道所有操作都已完成?您认为在最后一个上执行大量的.perform{}和fire.perform{try context.save}安全吗?因此,它将在最后运行该保存。操作队列具有operationCount属性。这够了吗?当KVO变为零时,您可能会收到通知。@danh,上下文不是操作队列,您建议使用上下文作为NSOperation,就像您提供的答案一样。或者我不明白这个方法,你能举个例子吗?你看到这个答案了吗@danh,是的,但据我所知,NSManagedContext没有用于挂起操作的计数器,我如何知道所有操作都已完成?您认为在最后一个上执行大量的.perform{}和fire.perform{try context.save}安全吗?因此,它将在最后运行该保存。操作队列具有operationCount属性。这够了吗?当KVO变为零时,您可能会收到通知。@danh,上下文不是操作队列,您建议使用conte xt作为您提供的答案中的一部分。或者我不明白这个方法,你能举个例子吗?
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()
}