Ios “如何修复”;n内部一致性异常';,原因:';无效更新:第0节中的行数无效。”;

Ios “如何修复”;n内部一致性异常';,原因:';无效更新:第0节中的行数无效。”;,ios,swift,uitableview,core-data,crash,Ios,Swift,Uitableview,Core Data,Crash,我正在使用swift创建一个新的iOS应用程序,需要帮助才能让我的tableView删除数据。我使用核心数据将数据保存在一对多关系中,因此选定的实体会删除,但在更新tableView时会崩溃 我以前创建过应用程序,但这是我第一次使用一对多数据存储方法。我也在谷歌上搜索过这个解决方案,但都没有成功。这是我的tableView编辑风格的代码 if editingStyle == .delete { context.delete(items[indexPath.row]) do {

我正在使用swift创建一个新的iOS应用程序,需要帮助才能让我的tableView删除数据。我使用核心数据将数据保存在一对多关系中,因此选定的实体会删除,但在更新tableView时会崩溃

我以前创建过应用程序,但这是我第一次使用一对多数据存储方法。我也在谷歌上搜索过这个解决方案,但都没有成功。这是我的tableView编辑风格的代码

if editingStyle == .delete {
    context.delete(items[indexPath.row])

    do {
        try context.save()

        self.tableView.beginUpdates()
        items.remove(at: indexPath.row)
        self.tableView.deleteRows(at: [indexPath], with: .fade)
        self.tableView.endUpdates()
    } catch let error as NSError {
        print("Could not save. \(error.localizedDescription)")
    }
}
我希望行与核心数据中的实体一起删除,但实际上它只是删除实体,然后在尝试更新tableView时崩溃。具体地说,我认为当它调用“deleteRows”时会崩溃,因为它会给出错误:

Project Aurora[14179:303873]***由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无效更新:节0中的行数无效。”。更新(2)后现有节中包含的行数必须等于更新(2)前该节中包含的行数,加上或减去从该节中插入或删除的行数(0插入,1删除),加上或减去移入或移出该节的行数(0移入,0移出).'

更多代码:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let count = fetchedRC.fetchedObjects?.count ?? 0
    return count
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "itemsTable", for: indexPath) as! ItemsTableViewCell

    items.append(fetchedRC.object(at: indexPath))

    if items[indexPath.row].isComplete == true {
        let attributeString = NSMutableAttributedString(string: items[indexPath.row].name!)

        attributeString.addAttribute(NSAttributedString.Key.strikethroughStyle, value: NSUnderlineStyle.single.rawValue, range: NSMakeRange(0, attributeString.length))
        cell.nameL.attributedText = attributeString

    } else {
        cell.nameL.text = items[indexPath.row].name
    }

    return cell
}

您使用的是一个
NSFetchedResultsController
,因此维护一个单独的数组(您的
)数组不是一个好主意;只需使用
对象(at:)
方法在需要时获取项目

cellForRowAt:
-
cellForRowAt:
中将项追加到
items
数组中时,您也会遇到一个问题:对于给定的
indexPath
,将多次调用
cellForRowAt:
,并且无法保证调用
cellForRowAt:
的顺序(例如,当您滚动表格视图时)

如果您使用的是
NSFetchedResultsController
,您确实应该实现其委托,并使用委托方法更新表

去掉
数组并使用以下内容:

extension ItemsTableViewController: NSFetchedResultsControllerDelegate {
    func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        self.tableView.beginUpdates()
    }

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

        let newIndexPath: IndexPath? = newIndexPath != nil ? IndexPath(row: newIndexPath!.row, section: 0) : nil
        let currentIndexPath: IndexPath? = indexPath != nil ? IndexPath(row: indexPath!.row, section: 0) : nil

        switch type {
        case .insert:
            self.tableView.insertRows(at: [newIndexPath!], with: .automatic)

        case .delete:
            self.tableView.deleteRows(at: [currentIndexPath!], with: .fade)

        case .move:
            self.tableView.moveRow(at: currentIndexPath!, to: newIndexPath!)

        case .update:
            self.tableView.reloadRows(at: [currentIndexPath!], with: .automatic)
        }
    }

    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        self.tableView.endUpdates()
    }
}
您的删除代码应为:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "itemsTable", for: indexPath) as! ItemsTableViewCell

    let item = fetchedRC.object(at:indexPath)

    if item.isComplete == true {
        let attributeString = NSMutableAttributedString(string: item.name ?? "")

        attributeString.addAttribute(NSAttributedString.Key.strikethroughStyle, value: NSUnderlineStyle.single.rawValue, range: NSMakeRange(0, attributeString.length))
        cell.nameL.attributedText = attributeString

    } else {
        cell.nameL.text = item.name
    }

    return cell
}
if editingStyle == .delete {
    context.delete(fetchedRC.object(at:indexPath))

    do {
        try context.save()
    } catch let error as NSError {
        print("Could not save. \(error.localizedDescription)")
    }
}

当您创建获取结果控制器时,请记住将
self
分配给
fetchedRC.delegate

尝试交换
项。删除…
beginUpdates
行。这也不起作用,我用完整错误更新了它,并删除了带有错误的注释,以减少混乱。您可以吗显示您的
numberOfRows
cellForRow
code?@Paulw11我用现在包含的numberOfRows和cellForRow更新了问题好的,谢谢。我实现了这一点,删除操作仍然有效,但似乎在删除行时没有调用扩展。为什么会这样?同样作为参考,我的视图控制器名称是“ItemsTableViewController”,如果这对扩展有帮助的话。我还更改了扩展名以扩展此视图。您是否将
self
分配给
fetchedRC.delegate
?此外,我在删除代码中遗漏了一个必需的更改-我已修复了itI,但没有。我如何将
self
分配为
fetchedRC.delegate
或分配到哪里?我注意到了这个要求并对其进行了更改,感谢您指出了这一点。假设您正在
viewDidLoad
或类似程序中创建获取结果控制器,您只需说
fetchedRC.delegate=self