我有一个包含图像< 1mb大小的表视图。滚动时,我从服务器中提取每个图像,然后将其保存到CoreData,除非它已经是本地的(用于缓存)。
这是我用来将每个图像保存到核心数据的功能......
// MARK: - Save Image to Core Data
func saveImageToCoreData(url: String,imageData: NSData) {
if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
if let managedContext = appDelegate.managedObjectContext as? NSManagedObjectContext {
let privateMoc = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
privateMoc.parentContext = managedContext
let entity = NSEntityDescription.entityForName("Images",
inManagedObjectContext: privateMoc)
let options = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext: privateMoc)
options.setValue(url, forKey: "url")
options.setValue(imageData, forKey: "imageData")
privateMoc.performBlock({
do {
try privateMoc.save()
print("Successfuly Saved an Image to Core Data.")
do {
try managedContext.save()
} catch {
}
} catch {
// Failed to save
}
})
}
}
}
如果我慢慢滚动,它可以正常工作。但是,当通过快速滚动调用此函数并因此调用' cellForRowAtIndexPath'很多时候,它给了我错误和崩溃。
错误示例:CoreData: error: (1555) UNIQUE constraint failed: ZIMAGES.Z_PK
我的保存功能不正确吗?或者可能是一次设置这么多线程来执行保存功能的问题?
非常感谢任何想法!谢谢!
答案 0 :(得分:1)
保存功能有几个问题:
1.您正在为每个图像创建一个私有队列上下文,这不是一个好主意。更好的方法是创建一个单独的私有队列上下文,并使用它来保存所有图像
2.不要在cellForRowAtIndexPath
中调用此保存图像功能,因为在向上和向下滚动桌面视图时将多次调用此委托功能。只需在其他地方执行此操作,例如在下载图像完成回调中
3.由于CoreData不是线程安全的,因此必须在私有上下文的线程而不是主线程上插入新映像。所以你必须这样做:
privateMoc.performBlock({
let entity = NSEntityDescription.entityForName("Images", inManagedObjectContext: privateMoc)
let options = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: privateMoc)
options.setValue(url, forKey: "url")
options.setValue(imageData, forKey: "imageData")
do {
try privateMoc.save()
print("Successfuly Saved an Image to Core Data.")
do {
try managedContext.save()
} catch {
}
} catch {
// Failed to save
}
})
完成这三项修复后,我相信问题应该得到解决。
答案 1 :(得分:0)
可能你可以使用SDWebImage。