Search code examples
swiftcore-datauiimageviewfetchbinary-data

binary data not fetching in UIImageView when called


My swift code below is using a textfield to enter a number. When the app builds 2 images are saved to core data binary data image. There is a index connected to it to control the order of the way the images are saved. When the user enters 1 in the textfield the 1st image should appear when 2 is entered. A gif is below of want I want to achieve.

enter image description here

import UIKit import CoreData

class ViewController: UIViewController,UITextFieldDelegate {


    @IBOutlet var labelName : UILabel!
    @IBOutlet var enterT : UITextField!
    @IBOutlet var pic : UIImageView!
    lazy var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext


    var dx = [UIImage]()
    var names = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()


        enterT.delegate = self

        pic.backgroundColor = .cyan


        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
        let managedContext = appDelegate.persistentContainer.viewContext
        let entity = NSEntityDescription.entity(forEntityName: "Users", in: managedContext)!
        let item = NSManagedObject(entity: entity, insertInto: managedContext)
             let item2 = NSManagedObject(entity: entity, insertInto: managedContext)
        let fetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")

        let vex = UIImage(named: "on.jpg")?.pngData()
        if let data = vex{
            item.setValue(data, forKey: "image")

        }




        let vex2 = UIImage(named: "house.jpg")?.pngData()
        if let data2 = vex2{
            item2.setValue(data2, forKey: "image")
        }




             do {
                 let result = try? managedContext.fetch(fetch) as? [Users]
                 print("Queen",result?.count)
                 try? managedContext.save()



             }
             catch {
                 print("Could not save")
             }


    }


    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        guard let text = (textField.text as? NSString)?.replacingCharacters(in: range, with: string), let index = Int(text) else { //here....
            // display an alert about invalid text
            return true
        }
        save(at: index )
        return true
    }

    func save(at index : Int) {
        let fetchRequest = NSFetchRequest<Users>(entityName: "Users")
        fetchRequest.predicate = NSPredicate(format: "idx == %d", Int32(index))
        do {
            if let user = try context.fetch(fetchRequest).first {


                pic.image = UIImage(data: user.image ?? Data())
            }
        } catch {
            print("Could not fetch \(error) ")
        }
        return
    }

    @IBAction func add(){


        fetch()
    }



    func fetch()
    {



        for i in 0..<dx.count {
            let newUser = Users(context: context)
            newUser.image = dx[i].jpegData(compressionQuality: 1)
            newUser.idx = Int32(i + 1)


        }



        print("Storing Data..")
        do {
            try context.save()
        } catch {
            print("Storing data Failed", error)
        }
        return
    }


}

Solution

  • You are mixing up fetching and saving

    • When you add items to the database create objects and save the context. Don't fetch.
    • When you load items from the database fetch the records. Don't save.

    I don't know if shouldChangeCharactersIn works as expected. The other code is supposed to work.

    And once again, on every application launch the (same) two items are added to the data base again.

    Be aware of that. If the items exist delete or comment out the line populateData() in viewDidLoad.

    class ViewController: UIViewController,UITextFieldDelegate {
    
    
        @IBOutlet var labelName : UILabel!
        @IBOutlet var enterT : UITextField!
        @IBOutlet var pic : UIImageView!
        lazy var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            enterT.delegate = self
    
            pic.backgroundColor = .cyan
            populateData()
        }
    
    
        func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
            guard let text = (textField.text as? NSString)?.replacingCharacters(in: range, with: string), let index = Int(text) else { //here....
                // display an alert about invalid text
                return true
            }
            loadImage(at: index )
            return true
        }
    
        func loadImage(at index : Int) {
            let fetchRequest = NSFetchRequest<Users>(entityName: "Users")
            fetchRequest.predicate = NSPredicate(format: "idx == %d", Int32(index))
            do {
                if let user = try context.fetch(fetchRequest).first {
                    pic.image = UIImage(data: user.image!)
                } else {
                   pic.image = nil
                }
            } catch {
                print("Could not fetch \(error) ")
            }
        }
    
        @IBAction func add(){
            // fetch()
        }
    
        func populateData()
        {
            let item = Users(context: context)
            let vex = UIImage(named: "on.jpg")!.pngData()
            item.image = vex
            item.idx = 1
    
            let item2 = Users(context: context)
            let vex2 = UIImage(named: "house.jpg")!.pngData()
            item2.image = vex2
            item2.idx = 2
    
            print("Storing Data..")
            do {
                try context.save()
            } catch {
                print("Storing data Failed", error)
            }
        }
    }