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

标签 ios swift uitableview core-data

我有一个表格 View ,其中包含大小 <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. 您正在为每个图像创建一个私有(private)队列上下文,这并不是一个好主意。更好的方法是创建一个单独的私有(private)队列上下文,并用它来保存所有图像。
2. 不要在cellForRowAtIndexPath中调用这个保存图片函数,因为这个委托(delegate)函数在tableview上下滚动时会被多次调用。只需在其他地方执行,例如在下载图像完成回调中。
3. 由于 CoreData 不是线程安全的,您必须在私有(private)上下文的线程而不是主线程上插入新图像。所以你必须这样做:

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
    }
})

在您完成这三个修复后,我相信问题应该得到解决。

关于ios - 滚动时从 'cellForRowAtIndexPath' 保存到 CoreData 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38688941/

相关文章:

swift - 如何通过 CoreData 中的关系传递谓词

swift - 为什么我的 ScrollView 中的内容 View 没有响应

ios - swift 2 上的 Facebook 样式标签

ios - iTunes API - 如何判断 Apple Music 上是否有歌曲?

swift - UIImageView 背景图像上的视差 UIScrollview

iOS Swift,UITableView 中的单元格不占据整个宽度

iOS 检索和排序具有关系的核心数据实体

ios - 自定义应用程序中的 UITableview 部分

iOS 内存管理工具

ios - BOOL 在模拟器上记录正常,但在 iPhone 上记录数字,如 96、-32 等