Swift tableviewdeleterows应用程序崩溃,即使数据已更新
我目前有一段代码,可以删除一个表行Swift tableviewdeleterows应用程序崩溃,即使数据已更新,swift,xcode,Swift,Xcode,我目前有一段代码,可以删除一个表行 extension HomeController: SwipeTableViewCellDelegate { func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? { guard orientation == .rig
extension HomeController: SwipeTableViewCellDelegate {
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
guard orientation == .right else { return nil }
print("in delete")
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { [self] action, indexPath in
print("currently deleting")
userHabitData.remove(at: indexPath.section)
tableView.deleteRows(at: [indexPath], with: .fade)
}
// customize the action appearance
deleteAction.image = UIImage(named: "delete")
return [deleteAction]
}
我确保在使用删除行之前更改数据源
userHabitData.remove(at: indexPath.section)
但是,代码仍然抛出此错误
线程1:“无效更新:节0中的行数无效。更新后现有节中包含的行数(1)必须等于更新前该节中包含的行数(1),加上或减去从该节插入或删除的行数(0插入,1删除)加上或减去移入或移出该节的行数(0移入,0移出)。”
这是我的完整视图控制器
//
// ViewController.swift
// Habit Tracker
//
// Created by Alan Weng on 11/24/20.
//
import UIKit
import SwipeCellKit
class tableViewCell: SwipeTableViewCell {
@IBOutlet weak var habitName: UILabel!
@IBOutlet weak var habitCount: UILabel!
var habit: Habit? {
didSet {
self.updateUI()
}
}
func updateUI() {
print("being run")
habitName?.text = habit?.title
habitCount?.text = habit?.detail
// progressLabel?.observedProgress = habit?.progress
}
}
class HomeController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var deno_label: UILabel!
@IBOutlet weak var tableView: UITableView!
let impactFeedbackgenerator = UIImpactFeedbackGenerator(style: .heavy)
@IBOutlet weak var deno_img: UIImageView!
var UserHabitDict: [String:String] = [:]
var userHabitData = [HabitDict]()
var userHabitName: String?
var userHabitCount: String?
let cellReuseID = "habitName"
let cellSpacingHeight: CGFloat = 15
let customRed = UIColor().customRed()
let customBlue = UIColor().customBlue()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
}
@IBAction func createNewGoal(_ sender: Any) {
let goalVC = storyboard?.instantiateViewController(withIdentifier: cellReuseID) as! CreateGoalController
impactFeedbackgenerator.prepare()
impactFeedbackgenerator.impactOccurred()
goalVC.habitDelegate = self
present(goalVC, animated: true, completion: nil)
}
// Think of how ios settings have different sections w diff spacings
func numberOfSections(in tableView: UITableView) -> Int {
return UserHabitDict.count
}
// Adjusts cell spacing between habits
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return cellSpacingHeight
}
// Adjust row height
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 75
}
// Allows the table to keep expanding based on how many habits are in the array
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
// Make the background color show through
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
headerView.backgroundColor = UIColor.clear
return headerView
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if habitIsEmpty() {
deno_img.alpha = 0.0
deno_label.alpha = 0.0
}
print("making habit")
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseID) as! tableViewCell
let dictKey = userHabitData[indexPath.section].getName()
let dictValue = userHabitData[indexPath.section].getCount()
cell.delegate = self
cell.backgroundColor = customBlue
cell.layer.cornerRadius = 10
cell.habit = Habit(title: dictKey, detail: dictValue)
print(userHabitData)
return cell
}
func tableView(_ tableView: UITableView, editActionsOptionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> SwipeOptions {
var options = SwipeOptions()
options.expansionStyle = .destructive
options.transitionStyle = .border
return options
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// note that indexPath.section is used rather than indexPath.row
// print("You tapped cell number \(indexPath.section).")
// let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseID) as! tableViewCell
// cell.habit?.updateDetail()
// tableView.reloadData()
// let dictKey = userHabitData[indexPath.section].getName()
// var dictValue = userHabitData[indexPath.section].getCount()
// print("over here")
// dictValue = String(Int(dictValue)! - 1)
// print(dictValue)
// cell.habit = Habit(title: dictKey, detail: dictValue)
// tableView.reloadData()
}
func allowMultipleLines(tableViewCell: UITableViewCell) {
tableViewCell.textLabel?.lineBreakMode = .byWordWrapping
}
func habitIsEmpty() -> Bool {
if userHabitData.isEmpty {
return false
} else {
return true
}
}
}
extension HomeController: CreateGoalDelegate {
func didTapSave(name: String, count: String) {
userHabitName = name
userHabitCount = count
UserHabitDict[name] = count
userHabitData.append(HabitDict(habitName: name, habitCount: count))
// tableView.insertRows(at: [IndexPath(row: userHabitData.count, section: 0)], with: .automatic)
tableView.reloadData()
print("in reload data")
}
}
extension UIColor {
func customRed() -> UIColor {
return UIColor(red: 0.607, green: 0.160, blue: 0.282, alpha: 1.00)
}
func customBlue() -> UIColor {
return UIColor(red: 0.509, green: 0.701, blue: 0.964, alpha: 1.00)
}
}
struct HabitDict {
let habitName: String
let habitCount: String
func getName() -> String {
return habitName
}
func getCount() -> String {
return habitCount
}
}
extension HomeController: SwipeTableViewCellDelegate {
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
guard orientation == .right else { return nil }
print("in delete")
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { [self] action, indexPath in
print("currently deleting")
userHabitData.remove(at: indexPath.section)
tableView.deleteRows(at: [indexPath], with: .fade)
}
// customize the action appearance
deleteAction.image = UIImage(named: "delete")
return [deleteAction]
}
}
任何帮助都将不胜感激 问题在于您的数据源不一致 在
delete
方法中,数据源数组是userHabitData
,但是在numberOfSections
中,您使用的是UserHabitDict
,在delete操作中不会更新
将numberOfSections
替换为
func numberOfSections(in tableView: UITableView) -> Int {
return userHabitData.count
}
然后删除部分(包括行)
请删除结构中的
getName
和getCount
函数。它们是多余的。直接使用名称和计数成员。您还可以从名称中删除冗余信息习惯Try而不是deleteRows
您可以尝试self.userHabitData.remove(位于:indexath.section)
?它仍然会给我相同的结果,我做了一些调试,发现删除后的数组计数实际上是0,而删除行之前的行计数是1。我相信这应该是正确的输出,这让我更加困惑,下面这行没有意义。同样,以下几行也没有意义。让dictKey=userHabitData[indexath.section].getName();让dictValue=userHabitData[indexPath.section].getCount()非常感谢您的回复!我应用了更改,但不幸的是,它仍然给我相同的错误消息。我还想知道为什么在tableView.deleteSections中有“at”,因为xcode在:“in call”处给了我一个错误“externeous argument label:”in call“不确定我是否遗漏了什么错误,请删除at:
。如果数据源数组是一致的,那么代码应该可以工作。由于某种原因,我的代码在不使用swipecellkit的情况下工作正常,我使用了UITableViewCell.EditingStyle,它工作正常!
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { [self] action, indexPath in
print("currently deleting")
userHabitData.remove(at: indexPath.section)
tableView.deleteSections([indexPath.section], with: .fade)
}