OllyR
OllyR

Reputation: 21

NSData variable not saving to CoreData

I'm trying to convert an image that the user has imported from the camera roll, convert the image to NSData and store it as binary data in CoreData. I have managed to convert it to binary and print it, but I doesn't store the value to core data. I have managed to store strings and other values to different attributes of the entity but for whatever reason the binary data isn't working.

func savingData(savingImage: UIImage){


        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
        let managedContext = appDelegate.persistentContainer.viewContext

        let userEntity = NSEntityDescription.entity(forEntityName: "Image", in: managedContext)!

        let data = savingImage.pngData()! as NSData


        if idLabel.text != "" {

            let user = NSManagedObject(entity: userEntity, insertInto: managedContext)
            user.setValue(idLabel.text, forKeyPath: "id")
            user.setValue(descriptionText.text, forKey: "imgdescription")
            user.setValue(confidenceLabel.text, forKey: "confidence")
            user.setValue(data, forKey: "binary")


            do {
                try managedContext.save()
                dataSaved.text = "Your answers have been saved! Click Home to return."


            } catch let error as NSError {
                print("Could not save. \(error), \(error.userInfo)")
                dataSaved.text="Error!"
            }
        }
    }
}

This is the code I have for storing the data. All the values save to core data and these values can be retrieved on the next class.

I've checked all the connections, triple checked that the naming of the entity and attributes and it still won't work.

Does anybody have any idea?

EDIT: the attribute "binary" is stored as 'binary data' in core data

func retrieveData() {

        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }

        let managedContext = appDelegate.persistentContainer.viewContext

        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Image")

        fetchRequest.fetchLimit = 1
        fetchRequest.predicate = NSPredicate(format: "id = %@", valueSelected)
        fetchRequest.sortDescriptors = [NSSortDescriptor.init(key: "id", ascending: false)]

        do {
            let result = try managedContext.fetch(fetchRequest)
            for data in result as! [NSManagedObject] {
                idText.text = data.value(forKey:"id") as? String
                descriptionText.text = data.value(forKey:"imgdescription") as? String
                confidenceText.text = data.value(forKey:"confidence") as? String
                photoView = data.value(forKey:"binary") as? UIImageView
            }

        } catch {

            print("Nothing found.")
        }
    }

This is how I'm calling it in the other class

Upvotes: 0

Views: 237

Answers (1)

vadian
vadian

Reputation: 285064

The main issue is that you are casting the Data to UIImageView which cannot work.

In the retrieveData method you have to create an UIImage from the data and assign the image to the image view

Basically there are a few improvements which increase safety.

  • Declare NSManaged objects with native Swift types (e.g. Data) and avoid optionals as much as possible.
  • Use always dot notation to access CoreData attributes rather than error-prone KVC
  • Use always a specific NSFetchRequest if you are going to access a specific entity

func savingData(savingImage: UIImage){

        // don't guard AppDelegate, the app won't even launch if it was missing so this line would be never reached
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let managedContext = appDelegate.persistentContainer.viewContext

        let imageEntity = NSEntityDescription.entity(forEntityName: "Image", in: managedContext)!

        let data = savingImage.pngData()!


        if !idLabel.text.isEmpty {

            let image = NSManagedObject(entity: imageEntity, insertInto: managedContext) as! Image
            image.id = idLabel.text
            image.imgdescription = descriptionText.text
            image.confidence = confidenceLabel.text
            image.binary = data

            do {
                try managedContext.save()
                dataSaved.text = "Your answers have been saved! Click Home to return."

            } catch let error as NSError {
                print("Could not save. \(error), \(error.userInfo)")
                dataSaved.text="Error!"
            }
        }
    }
}

func retrieveData() {

    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let managedContext = appDelegate.persistentContainer.viewContext

    let fetchRequest = NSFetchRequest<Image>(entityName: "Image")
    fetchRequest.fetchLimit = 1
    fetchRequest.predicate = NSPredicate(format: "id = %@", valueSelected)
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "id", ascending: false)]

    do {
        let images = try managedContext.fetch(fetchRequest)
        for image in images {
            idText.text = image.id
            descriptionText.text = image.imgdescription
            confidenceText.text = image.confidence
            if let imageData = image.binary {
               photoView.image = UIImage(data: imageData)
            }
        }

    } catch {
        print("Nothing found.", error)
    }
}

Upvotes: 1

Related Questions