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

here is coreData: don't forget to check Manual/None in Codegen in coreData Class
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
From the Xcode menu bar, choose Editor > Create NSManagedObject Subclass.
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 !