如何正确地从Core Data中的相关实体提取数据?

时间:2018-04-12 18:39:24

标签: core-data swift4

有两个实体:NameList(带有name属性)和ListArray(带有array属性)。它们通过多对多关系联系在一起: enter image description here

我希望在第一个Table视图中显示为表保存名称,当您选择某个名称时,请转到SecondTableView,其中将显示ListArray中的数据。并且还能够删除和编辑它们。会发生什么:我把两个表都放了,但我不能在第二个表上编辑任何东西。

class FirstTableView: UITableViewController, NSFetchedResultsControllerDelegate {

var fetchResultsController: NSFetchedResultsController<NameList>!
var fetchResultControllerArray: NSFetchedResultsController<ListArray>!

var toDoItems: [NameList] = []
var toDoArray: [ListArray] = []


override func viewDidLoad() {
    super.viewDidLoad()



    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.coreDataStack.persistentContainer.viewContext

    let fetchRequest: NSFetchRequest<NameList> = NameList.fetchRequest()
    let fetchRequesrArr: NSFetchRequest<ListArray> = ListArray.fetchRequest()

    do {
        toDoItems = try context.fetch(fetchRequest)
        toDoArray = try context.fetch(fetchRequesrArr)
    } catch {
        print(error.localizedDescription)
    }

}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
         }

// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return toDoItems.count

}


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

    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

    let nameList = toDoItems[(indexPath.row)]
    cell.textLabel?.text = nameList.name


    return cell
}


override func viewWillAppear(_ animated: Bool) {
}

override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
}

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

    let context = (UIApplication.shared.delegate as! AppDelegate).coreDataStack.persistentContainer.viewContext

    if editingStyle == .delete {
        let task = toDoItems[indexPath.row]
        let array = toDoArray[indexPath.row]
        context.delete(task)
        context.delete(array)
        do {
            try context.save()
        } catch {
            print(error.localizedDescription)
        }

        do {
            toDoItems = try context.fetch(NameList.fetchRequest())

            tableView.reloadData()
            print(toDoArray.count)
        } catch {
            print("Fetching Failed")
        }
    }
    print("del")
    //tableView.reloadData()
}

 // MARK: - Fetched Results Controller Delegate
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    tableView.beginUpdates()
}


func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {

    switch type {
    case .insert: guard let indexPath = newIndexPath else { break }
    tableView.insertRows(at: [indexPath], with: .fade)
    case .delete: guard let indexPath = indexPath else { break }
    tableView.deleteRows(at: [indexPath], with: .fade)
    case .update: guard let indexPath = indexPath else { break }
    tableView.reloadRows(at: [indexPath], with: .fade)
    default:
        tableView.reloadData()
    }
    toDoItems = controller.fetchedObjects as! [NameList]
    toDoArray = controller.fetchedObjects as! [ListArray]

}

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    tableView.reloadData()
    tableView.endUpdates()

}

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    let indexPath = self.tableView.indexPathForSelectedRow

    guard let selectedRow = indexPath?.row else { return }

    let selectedList = toDoArray[selectedRow]

    let destinationVC = segue.destination as? SecondTableView

    destinationVC?.readyList = selectedList.array as! [NSObject]
}
}

我会在决定中帮助他。

1 个答案:

答案 0 :(得分:0)

您的代码存在许多问题,但主要的问题是您并行处理两个实体,而应该从所选的NameList中获取ListArray实体数组。你需要它时做什么就像

let listArrayArray = selectedNameList.arrayItems

偏离主题:我建议不要在实体名称中使用像Array这样的单词或复数形式的任何内容,因为实体的名称应该描述一个对象。例如,ListItem可以是一个更好的建议。

因此无需获取ListArray对象,删除代码也是完全错误的。

查看代码我建议对FirstTableView进行以下更改:

  1. 删除toDoArray属性及其相关的任何代码。
  2. 在SecondTableView中添加,编辑和删除ListArray
  3. 更改prepare(for segue ...)的内容,如下所示
  4. 新准备:

    let indexPath = self.tableView.indexPathForSelectedRow
    guard let selectedRow = indexPath?.row else { return }
    
    let selectedList = toDoItems[selectedRow]
    
    let destinationVC = segue.destination as? SecondTableView
    
    destinationVC?.readyList = selectedList.arrayItems