ios - 通过两个不同的带部分的 NSFetchedResultsControllers 的单 TableView

标签 ios uitableview core-data swift3 nsfetchedresultscontroller

大家早上好。我正在使用 Swift 3.1.1、Xcode 8.3.2。我需要通过两个不同的 NSFetchedResultsControllers 将单个 TableView 连接到核心数据中的两个不同表(实体)。我已经创建了两个 NSFetchedResultsControllers,甚至从表中获取数据,但我遇到了如何告诉 TableView 第一个 Controller 应该响应第一部分而第二个 Controller 应该负责第二部分的问题。 我可以给你看代码:

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 中使用来自单个实体的继承,因为在现实生活中这是不可能的。 感谢您提供任何帮助或建议!

最佳答案

好的 - 我下载了你的代码,但有几个问题......

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
}

这应该让你上路。

关于ios - 通过两个不同的带部分的 NSFetchedResultsControllers 的单 TableView ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44131085/

相关文章:

ios - 为什么从自定义单元调用时 UIkeyboard 没有动画?

ios - 在同一个 View Controller 中使用 2 个 TableView (swift 3)

iphone - 可调整大小的 UITableViewCell

iOS 核心数据 : How do I add subsequent records to the 'many' of 1:many relationships?

swift - 如何将 UIView 存储在 CoreData 或 UserDefaults 中

swift - 如何删除核心数据 SwiftUI?

ios - RestKit 和压缩的 json

ios - Xamarin.Forms Observablecollection 在 ios 设备上引发异常

ios - Safari - iPhone 模拟器调试(通过 "develop")不再显示

objective-c - 分组 UITableView 部分的背景