如何在NSfetchedResultScontroller中的不同芯中实体之间切换?
我在项目中使用coredata
。它具有2个独立的实体
:货币
和crurner2
。这些实体具有相同的属性,但是存储一个填充tableView
的不同数据。 用户可以通过在应用程序设置中选择该选项来选择他想在tableView
中看到的哪些数据(我可以通过将其保存在userDefaults )。
这里的问题是如何使用不同的entity
数据填充表观视图?我不能仅像此处的字符串文字中的名称从Currency
更改为Currency2
:
private var fetchedResultsController: NSFetchedResultsController<Currency>!
它只会给我一个错误。因此,我假设我应该创建一个fetedResultScontroller ...:
private var fetchedResultsController: NSFetchedResultsController<Currency2>!
但是,我应该将以下所有代码加倍,因为我需要在它们之间切换。如果将来我需要在3或4个不同的实体
之间切换怎么办?
如何使代码可重复使用,同时使用nsfetchedresultscontroller
获得所需的开关结果?
目前,我的nsfetchedResultScontroller
设置如下:
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()
}
}
这也是我的coredatamanager.createcureatecurreencerfetchedResultscontroller
方法:
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)
}
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)
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您的实体始终具有相同的属性集,并且没有根本不同,请考虑将它们只是一个实体,并通过添加额外的属性来区分它们。这将使系统在不编写大量额外代码的情况下无限扩展,并且代码将更加简单。
如果您真的需要它们是独立的实体,我建议以下内容:
basecurrency
。货币
和Currency2
的父实体。basecurrency
中创建共享属性,然后将其从子体实体中删除。结果看起来像这样:nsfetchedResultScontroller
for AINTITY:请注意,请注意,此方法不接受任何形式的描述符或谓词,但是而不是枚举。它允许从具体的字段名称中抽象,并能够使用该方法中通用类型的关键路径。如果您需要更高级的排序/过滤功能,则可以通过引入更复杂的数据结构来描述过滤器和排序。
当然,您必须在此处明确指定控制器的类型。
这只是一个基本的有限示例,但希望您可以将其用作基础并在其顶部建立。
If your entities always have the same set of attributes and aren't fundamentally different, consider making them just one entity and differentiate them by adding an extra attribute. That will make the system infinitely extensible without writing much of extra code, and the code will be much simpler.
If you really need them be separate entities, I'd suggest the following:
BaseCurrency
.Currency
andCurrency2
.BaseCurrency
and remove them from the child entities. The result will look like this:NSFetchedResultsController
for any entity:Note that this method doesn't accept any sort descriptors or predicates but rather an enum. It allows to abstract from concrete field names and be able to use key paths of a generic types inside the method. If you need more advanced sorting/filtering capabilities, it's possible to build upon this idea by introducing more sophisticated data structures that describe filters and sorting.
You have to explicitly specify the type of the controller here of course.
This is just a basic limited example but hopefully you can use it as a foundation and build on top of it.