Fetched Results Controllers to manage records in Core Data in Swift

Posted By : Varun Wadhwa | 18-Dec-2017
Excel To HTML using codebeautify.org

In this blog, I’ll explain the use of Fetched Results Controller (by NSFetchedResutsController class ) to update TableView when a managed object updated in Core Data. Before proceeding, make sure you’ve basic knowledge of Core Data. Using NSFetchedResultsContoller and its delegate i.e NSFetchedResultsControllerDelegate It becomes easier to update the interface when there is any change in managed objects through delegation, Without it you’ve to write extra code to reflect those changes.


Step 1 :  Create an entity Employee with attributes emp_name and emp_id.

 


 

 

Step 2 :  Setup a tableview in view controller and conform to its delegate , we’ll populate this tableview with Fetched Results Controller which we’ll create in next step.

Step 3 :  In you view controller add the following code:

                
 fileprivate lazy var fetchedResultsController: NSFetchedResultsController
							<Employee> = {
        let fetchRequest : NSFetchRequest =  Employee.fetchRequest()
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "emp_id", ascending: true)]

        //managedObjectContext is your instance of NSManagedObjectContext 
        let fetchedResultsContoller = NSFetchedResultsController.init(fetchRequest: fetchRequest, managedObjectContext:  managedObjectContext , sectionNameKeyPath: nil, cacheName: nil)
        fetchedResultsContoller.delegate = self
         return fetchedResultsContoller
  }() 
						

Step 4 :  Fetch record from DB using performFetch() function.

                
 // call this function in viewWllAppear
  func getEmployees()  {
        do {
            try self.fetchedResultsController.performFetch()
        } catch let error {
            print("Error",error)
        }
    }

        

 

Step 5 :  Number of rows can be calculated as :

                
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
           guard let numberOfRows = fetchedResultsController.fetchedObjects?.count else {return 0}
        return numberOfRows
    }

 

Step 6 :  Data on tableview can be set incellForRowAt as :

 

   cell.emp_id_label.text =  fetchedResultsController.object(at: indexPath).emp_id
   cell.emp_name_label.text = fetchedResultsController.object(at: indexPath).emp_name


 

Step 7 :   Conform to protocol NSFetchedResultsControllerDelegate as :   

extension ViewController : NSFetchedResultsControllerDelegate {
    
    func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.beginUpdates()
    }
    
    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
        switch type {
        case .delete:
            tableView.deleteRows(at: [indexPath!], with: .fade )
        case.insert:
             tableView.insertRows(at: [newIndexPath!] , with: .fade)
        default:
            print("default")
        }
    }
    
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.endUpdates()
    }
}	

 

Step 8 :   Delete the row you want to delete by indexPath as :   

 

      DatabaseController.getContext.delete(fetchedResultsController.object(at: indexPath))
            do {
                try DatabaseController.getContext.save()
            } catch {
                print(error)
          }

      

 

You can place this code in tableview editingStyle if you’ve set true for canEditRowAt. Your row will automatically deleted as you’ve implemented delegate methods in step 7. Row will also added if you add a new record.

Thanks.

About Author

Author Image
Varun Wadhwa

Varun is a mobile developer with experience in various technologies like Titanium , Cordova and native iOS development.

Request for Proposal

Name is required

Comment is required

Sending message..