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

Ios 从TableView中删除行时CoreData应用程序崩溃,ios,core-data,tableview,swift4,Ios,Core Data,Tableview,Swift4,我有十几个表视图控制器,它们都能按预期工作,然后我有一个崩溃了: 由于未捕获异常“NSInternalInconsistencyException”而终止应用程序,原因:“无效更新:节0中的行数无效。”。更新(1)后现有节中包含的行数必须等于更新(1)前该节中包含的行数,加上或减去从该节中插入或删除的行数(0插入,1删除),加上或减去移入或移出该节的行数(0移入,0移出).' 执行此操作的代码已使用不同的选项进行了多次修改,但没有任何效果 import UIKit import CoreData

我有十几个表视图控制器,它们都能按预期工作,然后我有一个崩溃了:

由于未捕获异常“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
    }()
}
导入UIKit
导入CoreData
类QTypeVCY:UITableViewController,NSFetchedResultsControllerDelegate
{
将app=UIApplication.shared.delegate设为!AppDelegate
重写func viewDidLoad()
{
super.viewDidLoad()
}
重写func numberOfSections(在tableView:UITableView中)->Int
{
设截面=frc截面
返回节数
}
重写func tableView(tableView:UITableView,numberofrowsinssection:Int)->Int
{
防护罩let部分=自frc部分其他部分
{
fatalError(“fetchedResultsController中没有节”)
}
让sectionInfo=节[节]
返回sectionInfo.numberOfObjects
}
重写func tableView(tableView:UITableView,cellForRowAt indexath:indexPath)->UITableViewCell
{
let cell=tableView.dequeueReusableCell(标识符为“qqq”,表示:indexath)
让qtype=frc.object(at:indepath)
cell.textlab?.text=qtype.title
返回单元
}
重写func tableView(tableView:UITableView,commit editingStyle:UITableViewCellEditingStyle,forRowAt indexPath:indexPath){
如果editingStyle==.delete
{
做
{
让qtype=frc.object(at:indepath)
让context=self.frc.managedObjectContext
context.delete(qtype)
尝试context.save()
tableView.deleteRows(位于:[indexPath],带:.fade)
}
抓住
{
调试打印(错误)
}
}如果editingStyle==,则为else。插入
{
//创建相应类的新实例,将其插入数组,并向表视图添加新行
}    
}
惰性变量frc:NSFetchedResultsController=
{
让context=self.app.persistentContainer.viewContext
let-req:NSFetchRequest=Qtype.fetchRequest()
req.fetchBatchSize=10
让SortDescriptor 1=NSSortDescriptor(键:#键路径(Qtype.speciality),升序:true)
让SortDescriptor 2=NSSortDescriptor(键:#键路径(Qtype.title),升序:true)
req.sortDescriptors=[sortDescriptor1,sortDescriptor2]
设afrc=NSFetchedResultsController(fetchRequest:req,managedObjectContext:context,sectionNameKeyPath:nil,cacheName:nil)
afrc.delegate=self
做
{
试试afrc.performFetch()
}
抓住
{
打印(错误。本地化描述)
fatalError(“获取Qtype时中止”)
}
返回afrc
}()
}
崩溃发生在tableview.deleteRows语句中。我尝试过使用beginUpdate/endUpdates来包围代码,无论是否使用performFetch,甚至尝试过重新输入代码,以防我遗漏了一个输入错误。同样的基本代码也适用于其他表/视图控制器,仅此一个

实体只是由字符串组成的。我和其他实体有关系也有关系

自下次运行应用程序后,该行已被删除,但该行已丢失。此外,该表的另一个特点是,在添加新对象后调用reloadData不会添加行。我需要离开tableview并重新输入它。我确信这两者是相关的,但无法解释原因


由于最初发布了这篇文章,我包含了整个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)
让qtype=qtypes[indexath.row]
让context=self.frc.managedObjectContext
context.delete(qtype)
尝试context.save()

qtypes.remove(位于:indexPath.row)/我希望能够提供实际的解决方案,但是上面的代码现在可以工作了。我已经将XCode更新为1/24/18版本,但我认为这不是解决方案。我还剥离了崩溃的原始代码中的一些内容,但后来我把它们放回原处,它仍然有效。我怀疑我在某个地方输入了一个错误,但花了半个小时试图找到它,我宣布胜利并继续前进。

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

func tableView中的代码(\tableView:UITableView,trailingswipeactions在indexath:indexPath中为行配置)


那没用。我应该显示更多的代码。数组qtypes不是全局的,它是从数据存储中检索的。但是,您必须从表示数据源数组的数组中删除该项。我尝试过这样做,但相同的问题仍然存在。我修改了示例以显示数组的来源。是否使用
FetchedResultsController
的委托方法?如果是,则不能手动删除该行。如果
sections
是值类型,则必须将
qtype
重新分配给节。忘记
beginUpdates
endUpdatesself.tableviewArrayData.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
appDelegate.saveContext()