Swift 3 - 将图片保存到 Core Data

5
由于某些原因,我无法弄清楚如何将图像保存到核心数据并再次获取它们。我有一种感觉,这与我的类型有关,但请看一下:

Image is saved as Binary Data and stored in External Record File

我从服务器发起API调用获取数据。它返回一个base64字符串。 以下是获取数据的代码:

updateAccessTokenOnly(newAccessToken: aToken!)
saveImageToDB(brandName: imageBrandName, image: data! )

这里我将它保存到我的数据库中:

func saveImageToDB(brandName: String, image: Data) {
    dropImages(){tableDropped in
        let managedContext = getContext()
        let entity = NSEntityDescription.entity(forEntityName: "CoffeeShopImage", in: managedContext)!
        let CSI = NSManagedObject(entity: entity, insertInto: managedContext)

        CSI.setValue(image, forKey: "image")
        CSI.setValue(brandName, forKey: "brandName")

        do {
            try managedContext.save()
            print("saved!")
        } catch let error as NSError {
            print("Could not save. \(error), \(error.userInfo)")
        }
    }
}

然后获取它:

    func getImageFromDB(callback: @escaping (_ image: UIImage)-> ()) {

    let fetchRequest: NSFetchRequest<NSManagedObject> = NSFetchRequest(entityName: "CoffeeShopImage")

    do {
        let searchResults = try getContext().fetch(fetchRequest)

        for images in searchResults {
            print("vi når her ned i get image")
            if (images.value(forKey: "brandName")! as! String == "Baresso"){
                print(images.value(forKey: "brandName")! as! String)

                let image: Data = images.value(forKey: "image")! as! Data
                let decodedimage = UIImage(data: image)

                callback(decodedimage!)

            }
        }
    } catch {
        print("Error with request: \(error)")
    }
}

完整的错误日志:

https://docs.google.com/document/d/1gSXE64Sxtzo81eBSjv4bnBjBnnmG4MX2tuvNtnuJDIM/edit?usp=sharing

希望有人能够帮忙。先行致谢!

更新

我卸载了该应用程序,然后上述代码就可以工作了。但是图片会变成蓝色?(是的,我已经检查过从数据库发送的图片是正确的)。

有什么解决方案吗?

Pictures fetched from CoreData


2
更好的方法是将图像存储在DocumentDirectoryLibrary中,并将图像路径以字符串形式存储在CoreData中。在CoreData中以二进制数据或可转换形式存储图像会使编码/解码成为一项繁重的操作。 - viral
3个回答

12
替换
let image: Data = images.value(forKey: "image")! as! Data
let dataDecoded : Data = Data(base64Encoded: image, options: [])!
let decodedimage = UIImage(data: dataDecoded)
with
let image: Data = images.value(forKey: "image")! as! Data
let decodedimage = UIImage(data: image)

Base64是一种将数据转换为字符串的方式。在这里使用它没有任何意义。您已经从数据库中获取了数据,只需要将其转换为UIImage即可。

还要更改

let image = data?.base64EncodedData()
saveImageToDB(brandName: imageBrandName, image: image!)
to
saveImageToDB(brandName: imageBrandName, image: data!)

base64EncodedData将图像数据转换为UTF-8编码的base64字符串。这没有必要。

您应该从服务器获取base64编码的字符串,将其转换为数据,然后再也不需要使用base64。读写数据到您的数据库中,在读取后将其转换为UIImage。Base64是一种用于传输数据的编码方法。如果您没有与服务器通信,则无需使用base64。


1
嘿Jon,我的新好友哈哈。看起来我得到的错误是由于保存引起的。我尝试将其保存为字符串而不是数据。这似乎保存得很好,但是当我获取我的图像时,它们变成了蓝色方块,而不是图像。但目前,它无法使用上面的代码保存。 - Steffen L.
嗨Jon,我已做出你建议的更改,但保存时仍然出错。我已更新了代码并添加了完整的错误日志。 - Steffen L.
这意味着我甚至无法测试获取,因为它不会保存。 - Steffen L.
错误信息 "无法找到或自动推断迁移映射模型" 意味着您需要删除应用并重新安装。 - Jon Rose
我想知道用于创建图像的数据是否正确,或者它是图像显示的问题。如果图像大小正确,则意味着存在某些显示问题。如果图像大小不正确,则可能是服务器发送了错误的数据(可能是不受支持的格式)。或者你可能有base64数据,当你需要imageData时。 - Jon Rose
显示剩余7条评论

2
在Jon Rose提出的建议修改之后,我只需要添加一行代码即可。
.withRenderingMode(.alwaysOriginal)

我当时正在展示我的图片和代码,而且代码是可行的。


2

用户实体

保存图片:

 guard let managedObjectContext = managedObjectContext else { return }

    // Create User
    let user = User(context: managedObjectContext)

    // Configure User
    user.name = "name"
    user.about = "about"
    user.address = "Address"
    user.age = 30
    if let img = UIImage(named: "dog.png") {
        let data = img.pngData() as NSData?
        user.image = data
    }

获取图片:

// Create Fetch Request
    let fetchRequest: NSFetchRequest<User> = User.fetchRequest()

    // Configure Fetch Request
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
    let users = try! managedContext.fetch(fetchRequest)
    let user: User = users.first as! User
    if let imageData = user?.image {
            imgView.image = UIImage(data: imageData as Data)
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接