我的应用程序从某种格式转换为NSManagedObject
,因此最好的方法是使用NSOperation
(或Swift 3中的Operation
)从原始转换数据到NSManagedObject
并在完成所有操作后保存该上下文。
我不能为每个Operation
使用单独的上下文,因为我的转换器会生成关系(并且只能从相同的上下文访问它们),并且应用程序最多可以运行20次转换,因此它可以使用#39} ;创建新的上下文并在每次转换后保存它并不酷。
所以我需要创建单独的OperationQueue
并确保其中的所有操作都是从与上下文相同的线程执行的,我不知道该怎么做。
我只有一个想法:将Operation.main()
内的所有内容作为context.perform { }
启动,但我并不认为这是一个很好的解决方案。
我找到Regex to strip anything that isn't an html comment,但答案已经过时,我看到接受的答案显然不对。
答案 0 :(得分:3)
使用您自己的操作队列不是最好的方法。使用Core Data,您需要通过model
或var 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并发,然后使用mainQueueConcurrencyType
或privateQueueConcurrencyType
。如您所述使用自定义操作队列将无法正常工作。
这将使用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()
}