从滚动时'cellForRowAtIndexPath'崩溃保存到 CoreData



我有一个包含图像的表视图<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

我的保存功能不正确吗?或者一次设置这么多线程来执行保存功能可能有问题?

任何想法都非常感谢!谢谢

保存函数有几个问题:
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
    }
})

在你做了这三个修复之后,我相信这个问题应该会得到解决。

您可以使用SDWebImage。

最新更新