繁体   English   中英

从TableView删除行时,CoreData应用程序崩溃

[英]CoreData app crashes when deleting row from TableView

我有一打表视图控制器,它们都能按预期工作,然后出现崩溃:

由于未捕获的异常“ NSInternalInconsistencyException”而终止应用程序,原因:“无效更新:第0节中的行数无效。更新(1)之后现有节中包含的行数必须等于该行中包含的行数更新前的部分(1),加上或减去从该部分插入或删除的行数(已插入0,已删除1),加上或减去该部分移入或移出的行数(移入0,移入0)出)。”

执行此操作的代码已使用不同的选项进行了多次修改,但无效。

import UIKit
import CoreData

class QTypeVCY: UITableViewController, NSFetchedResultsControllerDelegate
{
    let app = UIApplication.shared.delegate as! AppDelegate

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

    override func numberOfSections(in tableView: UITableView) -> Int
    {
        let sections = frc.sections
        return sections!.count
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        guard let sections = self.frc.sections else
        {
            fatalError("No sections in fetchedResultsController")
        }
        let sectionInfo = sections[section]
        return sectionInfo.numberOfObjects
    }

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

        let qtype = frc.object(at: indexPath)
        cell.textLabel?.text = qtype.title

        return cell
    }

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete
        {
            do
            {
                let qtype = frc.object(at: indexPath)
                let context = self.frc.managedObjectContext
                context.delete(qtype)
                try context.save()
                tableView.deleteRows(at: [indexPath], with: .fade)
            }
            catch
            {
                debugPrint(error)
            }
        } else if editingStyle == .insert
        {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
        }    
    }

    lazy var frc: NSFetchedResultsController<Qtype> =
        {
            let context = self.app.persistentContainer.viewContext
            let req: NSFetchRequest<Qtype> = Qtype.fetchRequest()
            req.fetchBatchSize = 10

            let sortDescriptor1 = NSSortDescriptor(key: #keyPath(Qtype.specialty), ascending:true)
            let sortDescriptor2 = NSSortDescriptor(key: #keyPath(Qtype.title), ascending:true)
            req.sortDescriptors = [sortDescriptor1, sortDescriptor2]

            let afrc = NSFetchedResultsController(fetchRequest: req, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)

            afrc.delegate = self
            do
            {
                try afrc.performFetch()
            }
            catch
            {
                print(error.localizedDescription)
                fatalError("Abort while fetching Qtype")
            }
            return afrc
    }()
}

崩溃发生在tableview.deleteRows语句上。 我尝试过使用beginUpdate / endUpdates包围代码,无论是否使用performFetch,甚至尝试重新输入代码以防万一我错了错字。 同样的基本代码也可以在其他表/视图控制器上正常工作。

该实体仅由字符串组成。 无论是否与其他实体有关系,我都有它。

Qtype实体

自从下次运行该应用程序以来,该行已删除。 另外,关于此表的另一件事是,添加新对象后调用reloadData不会添加行。 我需要离开表格视图并重新输入。 我确定这两者是相关的,但不能说出原因。

自从最初发布此代码以来,我包括了整个VC代码,而不仅仅是有问题的代码。 我也尝试过将实体与没有发生此问题的其他实体交换,但是即使使用其他实体,程序仍然会崩溃。

您忘记也从数据源阵列中删除该项目

let qtype = qtypes[indexPath.row]
let context = self.frc.managedObjectContext
context.delete(qtype)
try context.save()
qtypes.remove(at: indexPath.row) // <-- 
tableView.deleteRows(at: [indexPath], with: .fade)

我希望我可以提供实际的解决方案,但是上面的代码现在可以使用了。 我已经将XCode更新为1/24/18版本,但是我认为这不是解决方案。 我还删除了崩溃的原始代码中的一些内容,但是后来我放回了它们,它仍然有效。 我怀疑我在某个地方有错字,但是在花了半个小时试图找到它之后,我宣布胜利并继续前进。

我只是解决了一个与您类似的问题。 在CoreData中删除数据时,TableView数据数组也会在appDelegate.saveContext appDelegate.saveContext()之前删除

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath)代码func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath)

self.tableviewArrayData.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
appDelegate.saveContext()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM