通过两个不同 NSFetchedResultsControllers 的单个表视图和部分
Posted
技术标签:
【中文标题】通过两个不同 NSFetchedResultsControllers 的单个表视图和部分【英文标题】:Single table view through two different NSFetchedResultsControllers with sections 【发布时间】:2017-05-23 09:37:42 【问题描述】:大家早上好。我正在使用 Swift 3.1.1、Xcode 8.3.2。我需要通过两个不同的 NSFetchedResultsController 将单个表视图连接到 Core Data 中的两个不同的表(实体)。我创建了两个 NSFetchedResultsControllers,甚至从表中获取数据,但我遇到了如何告诉表视图第一个控制器应该响应第一节,第二个控制器应该负责第二节的问题。 我可以给你看代码:
import UIKit
class ViewController: UIViewController
@IBOutlet weak var tv: UITableView!
@IBAction func pressed(_ sender: UIButton)
ModelA.read table1 in
ModelB.read table2 in
if table1.isEmpty
ModelA.save(recordToSave: [(a: 1, b: "a"), (a: 2, b: "b"), (a: 3, b: "c")])
ModelB.save(recordToSave: [(a: 4, b: 5.0, c: true), (a: 6, b: 7.0, c: false)])
self.tvReload()
else
self.tvReload()
var fetchedResultsControllerForModelA = CoreDataFunctions.fetchedResultsController
var fetchedResultsControllerForModelB = CoreDataFunctions.fetchedResultsController
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tvReload()
func modelOfTableA(indexPath: IndexPath) -> (forLabel1: String, forLabel2: String, forLabel3: String)?
if let fetchedResultsControllerForModelA = CoreDataFunctions.getNSManagedObjectForIndexPathOfTable(fetchedResultsController: fetchedResultsControllerForModelA, indexPath: indexPath)
if let model = ModelA.read(nsmanagedobject: fetchedResultsControllerForModelA)
return (forLabel1: "\(model.a)", forLabel2: model.b, forLabel3: "")
return nil
func modelOfTableB(indexPath: IndexPath) -> (forLabel1: String, forLabel2: String, forLabel3: String)?
if let fetchedResultsControllerForModelB = CoreDataFunctions.getNSManagedObjectForIndexPathOfTable(fetchedResultsController: fetchedResultsControllerForModelB, indexPath: indexPath)
if let model = ModelB.read(nsmanagedobject: fetchedResultsControllerForModelB)
return (forLabel1: "\(model.a)", forLabel2: "\(model.b)", forLabel3: "\(model.c)")
return nil
func tvReload()
fetchedResultsControllerForModelA = CoreDataFunctions(tableName: .a).fetchedResultsController(keyForSort: ModelA.a.rawValue, searchParameters: nil)
fetchedResultsControllerForModelB = CoreDataFunctions(tableName: .b).fetchedResultsController(keyForSort: ModelB.a.rawValue, searchParameters: nil)
do
try fetchedResultsControllerForModelA?.performFetch()
try fetchedResultsControllerForModelB?.performFetch()
DispatchQueue.main.async
self.tv.reloadData()
catch
print("Error")
func numberOfSectionsInTableView(_ tableView: UITableView) -> Int
return 1
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
if let sections1 = fetchedResultsControllerForModelA?.sections
if let sections2 = fetchedResultsControllerForModelB?.sections
return sections1[section].numberOfObjects + sections2[section].numberOfObjects
return sections1[section].numberOfObjects
return 0
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
if indexPath.section == 0
if let modelOfTable = modelOfTableA(indexPath: indexPath)
cell.l1.text = modelOfTable.forLabel1
cell.l2.text = modelOfTable.forLabel2
cell.l3.text = modelOfTable.forLabel3
else
if let modelOfTable = modelOfTableB(indexPath: indexPath)
cell.l1.text = modelOfTable.forLabel1
cell.l2.text = modelOfTable.forLabel2
cell.l3.text = modelOfTable.forLabel3
return cell
我找不到任何关于这个主题的教程,所以我在那里提问。我不想在 Core Data 中使用单个实体的继承,因为在现实生活中这是不可能的。 感谢您的任何帮助或建议!
【问题讨论】:
为什么你不是每个部分的单独数组? 即使没有 NSFetchedResultsControllers,我也可以对两个部分使用单个元组数组。我不认为,这是正确的方法 【参考方案1】:好的 - 我下载了你的代码,但有几个问题...
1) 如果您希望数据填充表中的两个部分,则表必须有两个部分 - 目前,您只返回 1,所以使用它(尽管您可能希望/需要根据检索到的数据进行不同的处理) :
func numberOfSectionsInTableView(_ tableView: UITableView) -> Int
if fetchedResultsControllerForModelA == nil || fetchedResultsControllerForModelB == nil
return 0
return 2
2) 对于每个部分的行数,您的代码很接近但不太正确...
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
if section == 0
if let sections = fetchedResultsControllerForModelA?.sections
return sections[0].numberOfObjects
else
if let sections = fetchedResultsControllerForModelB?.sections
return sections[0].numberOfObjects
return 0
3) 对于实际的 cellForRowAtIndexPath 数据,您的代码再次接近,但您需要跟踪每个部分要获取哪些数据...
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
if indexPath.section == 0
if let modelOfTable = modelOfTableA(indexPath: indexPath)
cell.l1.text = modelOfTable.forLabel1
cell.l2.text = modelOfTable.forLabel2
cell.l3.text = modelOfTable.forLabel3
else
// Each "Table data model" has only one section... since this is the 2nd table section, we need
// to change the section of the index path for our call to the data model
let dataIndexPath = IndexPath(row: indexPath.row, section: 0)
if let modelOfTable = modelOfTableB(indexPath: dataIndexPath)
cell.l1.text = modelOfTable.forLabel1
cell.l2.text = modelOfTable.forLabel2
cell.l3.text = modelOfTable.forLabel3
return cell
这应该会让你上路。
【讨论】:
但是,你能解释一下这部分吗?让 dataIndexPath = IndexPath(row: indexPath.row, section: 0) 您有两个数据模型 - 每个表部分一个。但是每个数据模型只有 ONE 数据部分。因此,如果您调用modelOfTableB()
并传递第二部分第一行的表的索引路径,您将要求“第 1 行,第 0 行”......这将失败,因为“第 1 部分”是 second 部分(从零开始的索引)。
好的,我想我现在明白了!再次感谢您!以上是关于通过两个不同 NSFetchedResultsControllers 的单个表视图和部分的主要内容,如果未能解决你的问题,请参考以下文章
关系的 NSFetchedResultsController 委托回调
NSFetchedResultsController - TableView 中的 UI 更新不完整