使用Swift 3和CoreData删除表视图行

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Swift 3和CoreData删除表视图行相关的知识,希望对你有一定的参考价值。

我正在尝试实施滑动以删除我的应用中的表格视图单元格而且我遇到了崩溃:

'无效更新:第0节中的行数无效。更新后的现有节中包含的行数(1)必须等于更新前的该节中包含的行数(1),加上或减去从该部分插入或删除的行数(插入0,删除1),加上或减去移入或移出该部分的行数(0移入,0移出)。

我有我的ViewController,在ViewControllerDataSource文件中,我符合UITableViewDataSource

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate,
        let managedObjectContext = appDelegate.managedObjectContext, editingStyle == .delete else { return }

    let request: NSFetchRequest<Meditation> = NSFetchRequest(entityName: "Meditation")
    let sortDescriptor = NSSortDescriptor(key: "date", ascending: false)
    request.sortDescriptors = [sortDescriptor]

    if let sessions = try? managedObjectContext.fetch(request) as [Meditation] {
        managedObjectContext.delete(sessions[indexPath.row])

        tableView.deleteRows(at: [indexPath], with: .fade)
        fetchEntries {
            tableView.reloadData()
        }
    }
}

这就是fetchEntries的样子

func fetchEntries(completion: (() -> Void)? = nil) {
    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate,
        let managedObjectContext = appDelegate.managedObjectContext
        else { return }

    var arrayOfEntries: [Entry] = []
    let request: NSFetchRequest<Meditation> = NSFetchRequest(entityName: "Meditation")
    let sortDescriptor = NSSortDescriptor(key: "date", ascending: false)
    request.sortDescriptors = [sortDescriptor]

    if let objects = try? managedObjectContext.fetch(request) as [Meditation] {
        meditationSessions = objects

        for (index, object) in objects.enumerated() {
            // set some values that correspond to visual elements in the cell

            let timeLabel = lengthMinutesLabel(minutesString: lengthMinutes(object.length))

            let entry = Entry(
                sessionLength: lengthMinutes(object.length),
                sessionTimeUnit: timeLabel,
                sessionStartTime: "(object.date.format())",
                sessionJournalEntry: object.journalEntry,
                sessionStreakTop: showStreak.top,
                sessionStreakBottom: showStreak.bottom
            )

            arrayOfEntries.append(entry)
            self.arrayOfEntries = arrayOfEntries
        }
    }

    completion?()
}

我不太确定我在这里做错了导致这次崩溃的原因。遗憾的是,如果崩溃是由竞争条件引起的,则CoreData删除功能没有完成块。

我已经为tableView:editingStyle:函数的最后7-9行尝试了各种不同的操作顺序无济于事。任何的意见都将会有帮助。谢谢!

答案

当你删除coreData中的数据时,除非你保存动作,否则它不会被coreData保存。删除操作应该是这样的..

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
  if editingStyle == .delete {
    managedObjectContext.delete(sessions[indexPath.row])
    do {
      try managedObjectContext.save()
      tableView.reloadData()
    } catch let error as NSError {
      print("Could not save. (error), (error.userInfo)")
    }
  }
}
另一答案

针对swift 3进行了更新:

如果要在使用Core Data时删除UITableView行/单元格,请在下面的代码行中使用:

import CoreData

// MARK: - 变量声明

@IBOutlet weak var mTableView: UITableView!
var manageObjectContext: NSManagedObjectContext!
var eventArray = [Event]()  // Where **Event** is an model name

// MARK: - ViewController LifeCycle方法

override func viewDidLoad() {
    super.viewDidLoad()
    manageObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    self.loadSaveData()
}

//从tableview中删除特定单元格/行

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

    let eventArrayItem = eventArray[indexPath.row]

    if editingStyle == .delete {
        manageObjectContext.delete(eventArrayItem)

        do {
            try manageObjectContext.save()
        } catch let error as NSError {
            print("Error While Deleting Note: (error.userInfo)")
        }
    }
    self.loadSaveData()
}

// MARK: - 实例方法

func loadSaveData()  {

    let eventRequest: NSFetchRequest<Event> = Event.fetchRequest()
    do{
        eventArray = try manageObjectContext.fetch(eventRequest)
        self.mTableView.reloadData()
    }catch
    {
        print("Could not load save data: (error.localizedDescription)")
    }
}
另一答案

我认为原因是由于对tableView.reloadData()的“额外”调用。只要你调用tableView.deleteRows,你就不应该调用reloadData - 所以要么调用其中一个,要么可以依赖于if,如果你想要一个淡入淡出动画(deleteRows)。

以上是关于使用Swift 3和CoreData删除表视图行的主要内容,如果未能解决你的问题,请参考以下文章

SWIFT - Coredata删除关系记录

Swift 3 - 表 VC(使用 coredata)和细节 VC 的故事板设计 *从默认信息的细节 VC 开始*

如何删除表视图核心数据中的行。斯威夫特3

使用 NSPredicate 对表视图中的核心数据进行排序 (Swift)

使用 CoreData 以编程方式创建实体/表,并在 Swift 3 for iOS 中将值插入该实体

通过两个不同 NSFetchedResultsControllers 的单个表视图和部分