1 个 UIViewController 中的 2 个 UITableViews 均从 CoreData 加载

2 UITableViews inside 1 UIViewController both loading from CoreData

我试图在 1 个 UIViewController 中有 2 个单独的 UITableView,但诀窍是我正在尝试这样做,以便它们都从 CoreDate 加载。

我试图通过使用与 UITableViewController 相同的样式来完成它,但我似乎 运行 遇到了问题。

我获取表格数据的方式是使用 FRC (NSFetchedResultsController),但我似乎只大声说每个 UIViewController 有 1 个。

这是我正在使用的 2 个 FRC 提取器。

FRC 1:

func getFRCIngredients() -> NSFetchedResultsController<Ent_Ingredients> {

    let fetchReq: NSFetchRequest<Ent_Ingredients> = Ent_Ingredients.fetchRequest()
    let sortDescriptor = NSSortDescriptor(key: "order", ascending: true)
    let predicate = NSPredicate(format: "recipeRel == %@", self.recipe!)

    fetchReq.sortDescriptors = [sortDescriptor]
    fetchReq.predicate = predicate

    let frc = NSFetchedResultsController(fetchRequest: fetchReq, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)

    return frc
}

FRC 2:

func getFRCDirections() -> NSFetchedResultsController<Ent_Directions> {

    let fetchReq: NSFetchRequest<Ent_Directions> = Ent_Directions.fetchRequest()
    let sortDescriptor = NSSortDescriptor(key: "order", ascending: true)
    let predicate = NSPredicate(format: "recipeRel == %@", self.recipe!)

    fetchReq.sortDescriptors = [sortDescriptor]
    fetchReq.predicate = predicate

    let frc = NSFetchedResultsController(fetchRequest: fetchReq, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)

    return frc
}

在尝试将第 2 个 FRC 上的委托设置为自身后,viewDidLoad() 中出现错误。当我考虑时,这是有道理的,您可能无法让它管理两组独立的数据。 错误:“libc++abi.dylib: terminating with uncaught exception of type NSException

override func viewDidLoad() {
    super.viewDidLoad()

    self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.plain, target: nil, action: nil)

    tableViewIngredients.dataSource = self
    tableViewIngredients.delegate = self
    tableViewIngredients.register(UITableViewCell.self, forCellReuseIdentifier: "recipeIngredientCell")

    tableViewDirections.dataSource = self
    tableViewDirections.delegate = self
    tableViewDirections.register(UITableViewCell.self, forCellReuseIdentifier: "recipeDirectionCell")

    recipeName.text = recipe!.name
    recipeImage.image = UIImage(data: recipe!.image as! Data)

    oldName = recipe!.name!

    frcIngredients = getFRCIngredients()
    frcIngredients!.delegate = self

    do {
        try frcIngredients!.performFetch()
    } catch {
        fatalError("Failed to perform initial FRC fetch for Ingredients")
    }

    frcDirections = getFRCDirections()
    frcDirections!.delegate = self  //<- ***ERRORS HERE***

    do {
        try frcDirections!.performFetch()
    } catch {
        fatalError("Failed to perform initial FRC fetch for Ingredients")
    }

    NotificationCenter.default.addObserver(self, selector: #selector(AddRecipesVC.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
}

我怎样才能完成我在这里想做的事情?我对 Xcode 和 Swift 还是比较陌生,所以非常感谢任何帮助。

谢谢!

原来我犯了一个愚蠢的错误。我忘记了我没有更新 Ent_Directions 实体中的属性名称,所以我总是调用一个不存在的属性。但以防万一这对以后的人有帮助,这是我最终用来让 2 个 UITableView 在单个 UIViewController 中工作的代码。我删除了与 UITableViews 无关的额外代码。

Swift 3.0:

class EditRecipesVC: UIViewController, UITableViewDataSource, UITableViewDelegate,  NSFetchedResultsControllerDelegate {

    // MARK: - Constants and Variables

    let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    var frcIngredients: NSFetchedResultsController<Ent_Ingredients>?
    var frcDirections: NSFetchedResultsController<Ent_Directions>?
    var recipe: Ent_Recipes?

    // MARK: - Class Loading Functions

    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.plain, target: nil, action: nil)

        tableViewIngredients.dataSource = self
        tableViewIngredients.delegate = self
        tableViewIngredients.rowHeight = UITableViewAutomaticDimension
        tableViewIngredients.estimatedRowHeight = 40

        tableViewDirections.dataSource = self
        tableViewDirections.delegate = self
        tableViewDirections.rowHeight = UITableViewAutomaticDimension
        tableViewDirections.estimatedRowHeight = 40

        recipeName.text = recipe!.name
        recipeImage.image = UIImage(data: recipe!.image as! Data)

        oldName = recipe!.name!

        frcIngredients = getFRCIngredients()
        frcIngredients!.delegate = self

        do {
            try frcIngredients!.performFetch()
        } catch {
            fatalError("Failed to perform initial FRC fetch for Ingredients")
        }

        frcDirections = getFRCDirections()
        frcDirections!.delegate = self

        do {
            try frcDirections!.performFetch()
        } catch {
            fatalError("Failed to perform initial FRC fetch for Ingredients")
        }

        NotificationCenter.default.addObserver(self, selector: #selector(AddRecipesVC.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    }

    // MARK: - Outlets and Actions

    @IBOutlet var tableViewIngredients: UITableView!
    @IBOutlet var tableViewDirections: UITableView!

    // MARK: - Table View Data Source

    func numberOfSections(in tableView: UITableView) -> Int {

        var frc: NSFetchedResultsController<NSFetchRequestResult>

        if (tableView == tableViewIngredients) {
            frc = frcIngredients as! NSFetchedResultsController<NSFetchRequestResult>
        } else {
            frc = frcDirections as! NSFetchedResultsController<NSFetchRequestResult>
        }

        if let sections = frc.sections {
            return sections.count
        }

        return 0
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        var frc: NSFetchedResultsController<NSFetchRequestResult>

        if (tableView == tableViewIngredients) {
            frc = frcIngredients as! NSFetchedResultsController<NSFetchRequestResult>
        } else {
            frc = frcDirections as! NSFetchedResultsController<NSFetchRequestResult>
        }

        if let sections = frc.sections {
            let currentSection = sections[section]
            return currentSection.numberOfObjects
        }

        return 0
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        if (tableView == tableViewIngredients) {
            let cell: RecipeIngredientTVCell = tableView.dequeueReusableCell(withIdentifier: "recipeIngredientCell", for: indexPath) as! RecipeIngredientTVCell

            return cell
        } else {
            let cell: RecipeDirectionTVCell = tableView.dequeueReusableCell(withIdentifier: "recipeDirectionCell", for: indexPath) as! RecipeDirectionTVCell

            return cell
        }
    }

    // MARK: - Custom Functions

    func getFRCIngredients() -> NSFetchedResultsController<Ent_Ingredients> {

        let fetchReq: NSFetchRequest<Ent_Ingredients> = Ent_Ingredients.fetchRequest()
        let sortDescriptor = NSSortDescriptor(key: "order", ascending: true)
        let predicate = NSPredicate(format: "recipeRel == %@", self.recipe!)

        fetchReq.sortDescriptors = [sortDescriptor]
        fetchReq.predicate = predicate

        let frc = NSFetchedResultsController(fetchRequest: fetchReq, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)

        return frc
    }

    func getFRCDirections() -> NSFetchedResultsController<Ent_Directions> {

        let fetchReq: NSFetchRequest<Ent_Directions> = Ent_Directions.fetchRequest()
        let sortDescriptor = NSSortDescriptor(key: "order", ascending: true)
        let predicate = NSPredicate(format: "recipeRel == %@", self.recipe!)

        fetchReq.sortDescriptors = [sortDescriptor]
        fetchReq.predicate = predicate

        let frc = NSFetchedResultsController(fetchRequest: fetchReq, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)

        return frc
    }
}