滚动时从“cellForRowAtIndexPath”保存到 CoreData 崩溃

Posted

技术标签:

【中文标题】滚动时从“cellForRowAtIndexPath”保存到 CoreData 崩溃【英文标题】:Saving to CoreData from 'cellForRowAtIndexPath' crashes when scrolling 【发布时间】:2016-07-31 22:36:22 【问题描述】:

我有一个表格视图,其中包含大小

这是我用来将每个图像保存到核心数据的函数...

// 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】:

您的保存功能存在几个问题: 1. 您正在为每个图像创建一个私有队列上下文,这并不是一个好主意。更好的方法是创建一个私有队列上下文,并将其用于保存所有图像。 2.不要在cellForRowAtIndexPath中调用这个保存图片函数,因为这个delegate函数会在tableview上下滚动的时候被调用多次。只需在其他地方执行此操作,例如在下载图像完成回调中。 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
    
)

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

【讨论】:

【参考方案2】:

也许你可以使用 SDWebImage。

【讨论】:

以上是关于滚动时从“cellForRowAtIndexPath”保存到 CoreData 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

如何在滚动时从左到右移动 div?

在滚动时从表格视图中删除反弹效果

如何修复滚动时从 UICollectionViewCell 中消失的图像

jQuery单击链接时从页面顶部滚动x像素

在停止滚动 ScrollView React Native 时从 api 获取数据

开始时从底部锚定的 UIScrollview