0

I am trying to delete binary data from core data. I am using a var int 'place' to determine what specific item I am trying to delete I am getting a runtime error under helpImage.shareInstance.deleteInfo(info: place) which is below.

Cannot convert value of type 'Int' to expected argument type 'Info'

What can I do to delete the 1st item saved in a core data binary attribute?

import UIKit;import CoreData

class ViewController: UIViewController {

    var place = 0
  
    
    override func viewDidLoad() {
        super.viewDidLoad()
     
        
        let gwen = UIImage(named: "unnamed.jpg")
        
        if let imageData = gwen.self?.pngData() {
            helpImage.shareInstance.saveImage(data: imageData)
        }
        
        let alz = UIImage(named: "alba.jpeg")
        
        if let imageData = alz.self?.pngData() {
            helpImage.shareInstance.saveImage(data: imageData)
        }
        

  
        
       
        
    }
    
   
   
    
    
   
   
   
    
    @objc func deleteM(){
       
       
            helpImage.shareInstance.deleteInfo(info: place)





        
        
    }
    
}



class helpImage: UIViewController{
    private class func getContext() -> NSManagedObjectContext {
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
    
        return appDelegate.persistentContainer.viewContext
    }
    static let shareInstance = helpImage()
    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    
 
    
    func saveImage(data: Data) {
        let imageInstance = Info(context: context)
        
        imageInstance.img = data
            
        do {
            try context.save()
          
        } catch {
            print(error.localizedDescription)
        }
    }
    
 
    func deleteInfo(info: Info) {
         do {
             try context.delete(info)
           
         } catch {
             print(error.localizedDescription)
         }
      }
  
    
   
}
  • may be these could be helpful to you : https://stackoverflow.com/questions/30200228/deleting-first-object-in-core-data-swift , https://stackoverflow.com/questions/38017449/swift-3-core-data-delete-object , https://stackoverflow.com/questions/45341545/swift-3-how-to-delete-the-single-record-in-the-core-data-when-a-uibutton-is-pre , https://stackoverflow.com/questions/50477777/how-do-i-delete-an-object-for-coredata-in-swift-4 – SwiftNewbie Jan 10 '23 at 05:05

1 Answers1

0

I'm also a newbie in swift and learning so if anyone has feedback, I'm more than happy to implement.

here is stroryBoard: on "Save" button click, we will save images in CoreData and on "Show" button click, we will display a tableView with our images fetched from CoreData enter image description here

here is coreData: don't forget to check Manual/None in Codegen in coreData Classenter image description here

then manually add coreData NSManagedObject SubClass files (there will be two files).

To generate the class and properties files initially:

source: https://developer.apple.com/documentation/coredata/modeling_data/generating_code

  1. From the Xcode menu bar, choose Editor > Create NSManagedObject Subclass.

  2. Select your data model, then the appropriate entity, and choose where to save the files. Xcode places both a class and a properties file into your project.

// this is how your "Picture+CoreDataClass.swift" looks like

import Foundation
import CoreData

@objc(Picture)
public class Picture: NSManagedObject {

}

// this how your "Picture+CoreDataProperties.swift" looks like

import Foundation
import CoreData


extension Picture {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Picture> {
        return NSFetchRequest<Picture>(entityName: "Picture")
    }

    @NSManaged public var pic: String?
    @NSManaged public var id: Int64

}

extension Picture : Identifiable {

}

I have used below extension to get currentTimeStamp as we will need unique ID for each of our coreData object, we will pass currentTimeStamp as ID to be unique.

// MARK: - Get the Current Local Time and Date Timestamp
source: https://stackoverflow.com/questions/46376823/ios-swift-get-the-current-local-time-and-date-timestamp

extension Date {
    static var currentTimeStamp: Int64{
        return Int64(Date().timeIntervalSince1970 * 1000)
    }
}

I have made CRUD functions in DataBaseHelper.swift file

// this "DataBaseHelper" Class

import Foundation
import UIKit
import CoreData

class DataBaseHelper {
    
    // MARK: - Get Context
    
    class func getContext() -> NSManagedObjectContext{
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        return appDelegate.persistentContainer.viewContext
    }
    
    static let shareInstance = DataBaseHelper()
        
    let context = getContext()
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Picture")
    
    // MARK: - Save Images
    
    func saveImage(picString: String, id: Int64 = Date.currentTimeStamp) {

// here I have passed id = Date.currentTimeStamp, as we need unique ID for each of our object in coreData and Date.currentTimeStamp will always give unique integer. we will use this ID to update and delete particular object.
        
        let entity = NSEntityDescription.entity(forEntityName: "Picture", in: context)!
        
        let image = NSManagedObject(entity: entity, insertInto: context)
                
        image.setValue(picString, forKey: "pic") // key should be same as the attributes taken in coreData Table.
        image.setValue(id, forKey: "id") // key should be same as the attributes taken in coreData Table.
        
        do {
            try context.save()
            print("Images saved in coreData")
            print("imageString: \(picString), id: \(id)") // this will print your entered (saved) object in coreData
        }  catch let error {
            print("Could not save images: \(error.localizedDescription)")
        }
    }
    
    // MARK: - fetch Images
    
    func fetchImages() -> [Picture] {
        
        var arrImages = [Picture]()
        
        fetchRequest.returnsObjectsAsFaults = false
        
        do {
            arrImages = try context.fetch(fetchRequest) as? [Picture] ?? [Picture]()
            print("Images while fetching from coreData: \(arrImages)") // this will print all objects saved in coreData in an array form.
        } catch let error {
            print("Could not fetch images: \(error.localizedDescription)")
        }
        return arrImages
    }
    
    // MARK: - fetch Images by ID
    
    func fetchImagesByID(id: Int64) -> Picture {
        
        fetchRequest.returnsObjectsAsFaults =  false
        let predicate = NSPredicate(format: "id == \(id)")
        fetchRequest.predicate = predicate
        
        let result = try? context.fetch(fetchRequest)
        return result?.first as? Picture ?? Picture()
    }
    
    // MARK: - Update Image
    
    func updateImage(object: Picture) {
        
        let image = fetchImagesByID(id: object.id) // we will first fetch object by its ID then update it.
        
        image.pic = object.pic
        
        do {
            try context.save()
            print("Image updated in CoreData")
            print("after updating Picture --> \(object)")
        } catch let error {
            print("Could not update Picture: \(error.localizedDescription)")
        }
    }
    
    // MARK: - Delete Image
    
    func deleteImage(id: Int64) {
        
        let image = fetchImagesByID(id: id) // we will first fetch object by its ID then delete it.
        
        context.delete(image)
        
        do {
            try context.save()
            print("Image deleted from CoreData")
        } catch let error {
            print("Could not delete Image --> \(error.localizedDescription)")
        }
    }
}

here is our ViewController:

I have added 4 images in Assets folder.

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var btnSaveImages: UIButton!
    @IBOutlet weak var tableViewPicture: UITableView!
    @IBOutlet weak var btnShowImages: UIButton!
    
    
    var resultImages = [Picture]() // this an an instance of our model class (coreData)

    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.navigationItem.title = "CoreData Demo"
        
        setUpTableView()
        
    }
    
    // MARK: - Save Images
    
    func saveImagesInCoreData() {
        
        // I have added 4 images in Assets folder, here we will save 3 images in CoreData
        
        let image1 = "flower1"
        let image2 = "flower2"
        let image3 = "flower3"
        
        DataBaseHelper.shareInstance.saveImage(picString: image1)
        DataBaseHelper.shareInstance.saveImage(picString: image2)
        DataBaseHelper.shareInstance.saveImage(picString: image3)
    }
    
    // MARK: - Fetch Images
    
    func fetchImagesFromCoreData() {
        
        resultImages = DataBaseHelper.shareInstance.fetchImages() // this will give fetched images
        
    }
    
    // MARK: - Set Up TableView
    
    func setUpTableView () {
        
        tableViewPicture.delegate = self
        tableViewPicture.dataSource = self
    }
    
    // MARK: - Button Save Images Event

    @IBAction func btnSaveImages_Event(_ sender: UIButton) {
        
        saveImagesInCoreData() // save images in CoreData
        
    }
    
    // MARK: - Button Show Images Event
    
    @IBAction func btnShowImages_Event(_ sender: UIButton) {
        
        fetchImagesFromCoreData() // fetch Images from CoreData
        self.tableViewPicture.reloadData() // reload tableView
    }
}

// MARK: - Extesnion TableViewDelegate and TableViewDataSource

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        return resultImages.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell") ?? UITableViewCell()
        
        cell.imageView?.image = UIImage(named: resultImages[indexPath.row].pic ?? "")
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        
        return true
    }
    
    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        
        let editAction = UITableViewRowAction(style: .default, title: "Edit") { (action, indexPath) in
            print("Action Edit")
            
            // here we will edit image of selected row in our tableView, we will update selected row with new image that is "flower4".
            
            let image4 = "flower4"
            
            self.resultImages[indexPath.row].pic = image4
            
            DataBaseHelper.shareInstance.updateImage(object: self.resultImages[indexPath.row]) // update image of selected row in tableView
            self.tableViewPicture.reloadData()
                                    
        }
        
        editAction.backgroundColor = .lightGray
        
        let deleteAction = UITableViewRowAction(style: .destructive, title: "Delete") { (action, indexPath) in
            print("Action Delete")
            
            // here we will delete an object of selected row in our tableView.
            
            DataBaseHelper.shareInstance.deleteImage(id: self.resultImages[indexPath.row].id) // delete object of selected row in tableView
            self.resultImages.remove(at: indexPath.row) // remove from resultImages array
            self.tableViewPicture.reloadData()
        }
        
        return [deleteAction, editAction]
        
    }
    
}

if you have doubt feel free to ask !

SwiftNewbie
  • 285
  • 1
  • 9