None of the answers above helped me in using Core Data with the FetchedResultsController for a tableView . As such, here is my implementation for handling deletion below. My example uses a simple example, assuming you want to remove the image from scrolling left on the table and choose the default delete option.
Swift 3 Solution for FetchedResultsController Implementaitons
First add this delegate method to represent the table to allow editing when scrolling through a row.
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { print("editing style delete detected") let context = DataController.sharedInstance().managedObjectContext let picture = self.fetchedResultsController.object(at: indexPath) as Pictures context.delete(picture) //Actually remove picture from storage on the device. let fileManager = FileManager.default let imagefilepath = "\(AppDelegate.appDelegate.applicationDocumentsDirectory())/\(picture.filepath!)" do { try fileManager.removeItem(atPath: imagefilepath) } catch let error as NSError { print("Ooops! Something went wrong while trying to delete picture file: \(error)") } //Save the context change. AppDelegate.appDelegate.saveContext() tableView.reloadData()//update changes } }
Once you do this, make sure that the fetchedResultsController has its own delegate set by your controller and that implements these methods.
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { switch(type){ case .insert: break; case .delete: print("delete detected on FRC Delegate") tableView.deleteRows(at: [indexPath!], with: .fade) break; case .update: break; case .move: break; } }
The secret here is to access the object using the fetchedResultsController.object method
let picture = self.fetchedResultsController.object(at: indexPath) as Pictures
So you can run
context.delete(picture)
which can remove NSManagedObjects.
Additional information related to my implementation (read below if you need additional information)
----------------------------------------------- --- -------------------------
Photo + CoreDataProperties.swift
import Foundation import CoreData extension Pictures { @nonobjc public class func fetchRequest() -> NSFetchRequest<Pictures> { return NSFetchRequest<Pictures>(entityName: "Pictures"); } @NSManaged public var date: NSDate? @NSManaged public var desc: String? @NSManaged public var filepath: String? @NSManaged public var type: String? @NSManaged public var workorder: Workorders? }
Pictures + CoreDataClass.swift
import Foundation import CoreData public class Pictures: NSManagedObject { }
Below is my coreData stack handler.
DataController.swift
import UIKit import CoreData class DataController: NSObject { var managedObjectContext: NSManagedObjectContext static var dataController: DataController! override init() { // This resource is the same name as your xcdatamodeld contained in your project. guard let modelURL = Bundle.main.url(forResource: "WorkOrders", withExtension: "momd") else { fatalError("Error loading model from bundle") } // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model. guard let mom = NSManagedObjectModel(contentsOf: modelURL) else { fatalError("Error initializing mom from: \(modelURL)") } let psc = NSPersistentStoreCoordinator(managedObjectModel: mom) managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) managedObjectContext.persistentStoreCoordinator = psc let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let docURL = urls[urls.endIndex-1] /* The directory the application uses to store the Core Data store file. This code uses a file named "DataModel.sqlite" in the application documents directory. */ let storeURL = docURL.appendingPathComponent("WorkOrders.sqlite") do { let options = [NSSQLitePragmasOption: ["journal_mode": "DELETE"]] try psc.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: options) } catch { fatalError("Error migrating store: \(error)") } } class func sharedInstance() -> DataController { if (dataController != nil) { return dataController } dataController = DataController() return dataController } }
Here, my save method is designed to maintain context.
AppDelegate.swift
import UIKit import CoreData @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? static var appDelegate: AppDelegate!