现在我不明白了。他们是说我正在使用相同的托管吗
对象上下文还是我应该使用相同的托管对象上下文?如果我
我正在使用同一个,为什么我每次都会创建一个新的
环形?或者,如果我应该只使用一个全局上下文,我该怎么做
不会导致内存泄漏?
让我们看看代码的第一部分......
while (thereAreStillMoreObjectsToAdd) {
let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
managedObjectContext.undoManager = nil
现在,由于您似乎将 MOC 保留在应用程序委托中,因此您可能正在使用模板生成的核心数据访问代码。即使您不是,您的情况也极不可能managedObjectContext
每次调用 access 方法时都会返回一个新的 MOC。
Your managedObjectContext
变量只是对存在于 App Delegate 中的 MOC 的引用。因此,每次循环时,您只是复制引用。每次循环时引用的对象都是完全相同的对象。
因此,我认为他们是在说你没有使用单独的上下文,我认为他们是对的。相反,您每次循环时都会使用对同一上下文的新引用。
现在,您的下一组问题与性能有关。您的其他帖子引用了一些不错的内容。回去再看一遍。
他们的意思是,如果你想做一个大的导入,你应该创建一个单独的上下文,专门用于导入(Objective C,因为我还没有时间学习 Swift)。
NSManagedObjectContext moc = [[NSManagedObjectContext alloc]
initWithConcurrencyType:NSPrivateQueueConcurrencyType];
然后,您可以将该 MOC 附加到持久存储协调器。使用performBlock
然后,您可以在一个单独的线程中导入您的对象。
批处理的概念是正确的。你应该保留那个。但是,您应该将每个批次包装在自动释放池中。我知道你可以快速做到这一点...我只是不确定这是否是确切的语法,但我认为它很接近...
autoreleasepool {
for item in array {
let newObject = NSEntityDescription.insertNewObjectForEntityForName ...
newObject.attribute1 = item.whatever
newObject.attribute2 = item.whoever
newObject.attribute3 = item.whenever
}
}
在伪代码中,它看起来像这样......
moc = createNewMOCWithPrivateQueueConcurrencyAndAttachDirectlyToPSC()
moc.performBlock {
while(true) {
autoreleasepool {
objects = getNextBatchOfObjects()
if (!objects) { break }
foreach (obj : objects) {
insertObjectIntoMoc(obj, moc)
}
}
moc.save()
moc.reset()
}
}
如果有人想把伪代码变成 swift,我没问题。
自动释放池确保由于创建新对象而自动释放的任何对象都会在每个批次结束时释放。一旦对象被释放,MOC 就应该拥有对 MOC 中对象的唯一引用,并且一旦发生保存,MOC 就应该为空。
诀窍是确保作为批处理一部分创建的所有对象(包括表示导入数据和托管对象本身的对象)都在自动释放池内创建。
如果您执行其他操作(例如获取数据以检查重复项)或具有复杂的关系,则 MOC 可能不完全为空。
因此,您可能需要添加相当于[moc reset]
保存后确保MOC确实为空。