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

时间:2017-01-30 01:21:42

标签: uitableview uiviewcontroller swift3 xcode8 nsfetchedresultscontroller

我试图在1个UIViewController中有2个独立的UITableViews,但诀窍是我试图这样做,所以他们都从CoreDate加载。

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

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

以下是我使用的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
}

在我尝试将第二个FRC上的委托设置为self后,我在viewDidLoad()内得到了错误。当我考虑它时,这是有道理的,你可能无法管理两组独立的数据。 错误:&#34; libc++abi.dylib: terminating with uncaught exception of type NSException&#34;

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来说还是比较新的,所以任何帮助都会非常感激。

谢谢!

1 个答案:

答案 0 :(得分:0)

事实证明我犯了一个愚蠢的错误。我忘记了我没有更新Ent_Directions实体中的属性名称,因此我总是调用一个不存在的属性。但是为了以后这可以帮助某人,这是我最终使用的代码,以便在单个UIViewController中使用2个UITableViews。我删除了与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
    }
}