我正在使用swift创建一个新的iOS应用程序,并且需要帮助我的tableView删除数据。我正在使用Core Data以一对多的关系保存数据,并且我拥有它,因此所选实体被删除,但是在更新tableView时崩溃。
我以前创建过应用程序,但这是我第一次使用一对多数据存储方法。我也有谷歌解决方案,但没有一个工作。这是我的tableView editStyle的代码。
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)")
}
}
我希望该行与Core Data中的实体一起删除,但实际上只是删除该实体,然后在尝试更新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
}
答案 0 :(得分:0)
您使用的是NSFetchedResultsController
,因此维护一个单独的数组(您的items
)数组不是一个好主意;只需在需要时使用object(at:)
方法即可获取物品。
在将项目追加到items
中的cellForRowAt:
数组中时,您也遇到问题-对于给定的cellForRowAt:
,indexPath
会被多次调用,并且在那里无法保证cellForRowAt:
的调用顺序(例如,滚动表格视图时)。
如果您使用的是NSFetchedResultsController
,则您确实应该实现其委托并使用委托方法来更新表。
摆脱items
数组,并使用类似以下内容的东西:
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()
}
}
您的cellForRowAt
应该是:
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
。