I am using a CoreData
in my project. It has 2 separate Entities
: Currency
and Currency2
. The entities have identical attributes, but store a different data which populates a tableView
. And user can choose which data he wants to see in the tableView
by picking the option in app settings (I can store his choice by saving it in UserDefaults
).
The problem here is how can I populate the tableView with a different Entity
data? I can't just change a name like in string literal in here from Currency
to Currency2
:
private var fetchedResultsController: NSFetchedResultsController<Currency>!
It will just give me an error. So I assume I should create one more fetchedResultsController...:
private var fetchedResultsController: NSFetchedResultsController<Currency2>!
But then I should double all the below code since I need to switch between them. And what If in future I will need to switch between 3 or 4 different Entities
?
How can I make the code reusable and at the same time receive a desired switch result with NSFetchedResultsController
?
For now my NSFetchedResultsController
set up as follows:
class CurrencyViewController: UIViewController {
private var fetchedResultsController: NSFetchedResultsController<Currency>!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
setupFetchedResultsController()
}
//MARK: - TableView DataSource Methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fetchedResultsController.sections![section].numberOfObjects
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "currencyCell", for: indexPath) as! CurrencyTableViewCell
let currency = fetchedResultsController.object(at: indexPath)
cell.shortName.text = currency.shortName
cell.fullName.text = currency.fullName
return cell
}
//MARK: - NSFetchedResultsController Setup & Delegates
func setupFetchedResultsController(with searchPredicate: NSPredicate? = nil) {
let predicate = NSPredicate(format: "isForCurrencyScreen == YES")
var sortDescriptor: NSSortDescriptor {
if pickedSection == "По имени" {
return NSSortDescriptor(key: "fullName", ascending: sortingOrder)
} else {
return NSSortDescriptor(key: "shortName", ascending: sortingOrder)
}
fetchedResultsController = coreDataManager.createCurrencyFetchedResultsController(with: predicate, and: sortDescriptor)
fetchedResultsController.delegate = self
try? fetchedResultsController.performFetch()
tableView.reloadData()
}
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
}
And this is also my coreDataManager.createCurrencyFetchedResultsController
method:
private let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
func createCurrencyFetchedResultsController(with predicate: NSPredicate? = nil, and sortDescriptor: NSSortDescriptor? = nil) -> NSFetchedResultsController<Currency> {
let request: NSFetchRequest<Currency> = Currency.fetchRequest()
let baseSortDescriptor = NSSortDescriptor(key: "shortName", ascending: true)
request.predicate = predicate
return NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
}