在swift中将图像存储在Core Data中

时间:2018-06-13 09:34:44

标签: swift core-data

我正在尝试将我的应用中的本地图像保存到核心数据模型中。我创建了实体并为图像创建了一个属性。但是,当我运行应用程序时,它会因此错误而崩溃,Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "image"; desired type = NSData; given type = UIImage; value = <UIImage:我保存图像的代码是,

 let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    let entity = NSEntityDescription.entity(forEntityName: "Saloon", in: context)
    let newUser = NSManagedObject(entity: entity!, insertInto: context)

    newUser.setValue(nameLbl.text, forKey: "name")
    newUser.setValue(addressLbl.text, forKey: "address")
    newUser.setValue(distanceLbl.text, forKey: "distance")
    newUser.setValue(rating.text, forKey: "rating")
    newUser.setValue(imageView.image, forKey: "image") as? UIImage
 do {
        try context.save()
        print("saved")
    } catch {
        print("Failed saving")
    }

这就是我提取图像的方式,

let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Saloon")
    //request.predicate = NSPredicate(format: "age = %@", "12")
    request.returnsObjectsAsFaults = false
    do {
        let result = try context.fetch(request)
        for data in result as! [NSManagedObject] {

            print(data.value(forKey: "name") as! String)
            let image: Data = data.value(forKey: "image")! as! Data
            let decodedimage = UIImage(data: image)
            imageView2.image = decodedimage
            name2Lbl.text = data.value(forKey: "name") as? String
            address2Lbl.text = data.value(forKey: "address") as? String
            distance2Lbl.text = data.value(forKey: "distance") as? String
            rating2Lbl.text = data.value(forKey: "rating") as? String
        }

    } catch {

        print("Failed")
    }

2 个答案:

答案 0 :(得分:0)

您无法直接在Core Data中保存UIImage。相反,您必须将图像转换为NSData(如错误消息中的“desired type = NSData”)。这是UIImage的扩展名:

extension UIImage {
    func jpegData(withCompressionQuality quality: CGFloat) -> Data? {
        return autoreleasepool(invoking: {() -> Data? in
            return UIImageJPEGRepresentation(self, quality)
        })
    }
}

quality是0.0到1.0之间的值,后者表示JPEG压缩图像的最高质量。 autoreleasepool的使用有助于避免在使用UIImageJPEGRepresentation时偶然发现的内存泄漏问题。

然后,您可以使用以下代码保存图像:

if let imageData = imageView.image .jpegData(withCompressionQuality: 1.0) {
    newUser.setValue(imageData, forKey: "image")
}
顺便说一下,如果这是你需要的,你也可以转换为PNG而不是JPEG,这是无损的。使用UIImagePNGRepresentation代替UIImageJPEGRepresentation

答案 1 :(得分:0)

与上一个答案不同,可以将图像作为UIImage存储在Core Data中。尽管这不被认为是一种好习惯,因为数据库并不用于存储文件。我们不使用核心数据直接存储图像,而是使用文件路径存储图像数据到手机上。

无论如何,下面展示了我在开发附带项目时发现的最佳方法

  1. Set the entity codeGen to Manual/None

  2. 选择要为图像类型的属性,然后选择transformable作为其类型

  3. Enter Custom class identifier as UIImage

  4. 转到编辑器,然后选择Create NSManagedObject Subclass

  5. 该流程将根据您的实体数创建2个swift文件(我只有1个实体)。现在,选择<EntityName> + CoreDataProperties.swift文件和import UIKit

如果在@NSManaged public var <attributeName: UIImage?上单击Jump to Definition,就可以登陆UIImage definition,那么您的工作就完成了。

对实体执行操作就像您将要进行的一样,您将可以通过向下广播<EntityName>?.value(forKey: "<attributeName>") as? UIImage来获取,保存和编辑图像属性。

我不得不将实体用作NSManagedObject类型,由于某种原因,我无法直接从创建的子类访问图像。