微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在带有自定义表格视图单元格的表格视图中滑动删除?

如何解决如何在带有自定义表格视图单元格的表格视图中滑动删除?

目前,我有一个屏幕显示带有自定义单元格的 TableView,每个单元格都有一个文本字段和一个按钮。我将文本字段的数据输入存储到 taskName dict 和按钮的标题选择(从弹出屏幕)到 tasktime dict

但是,我的问题是当我在 TableView 中滑动以删除一行时,它会删除存储在该行中的数据,但不会删除该行本身(如下面的动画所示)。

这是我的代码

带有 TableView + 自定义单元格的屏幕

class TaskListViewController: UIViewController {
    
    @IBOutlet weak var taskList: SelfSizedTableView!
    
    var taskCount: Int = 1
    var taskName = [Int:String]()
    var tasktime = [Int:String]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set initial tasktime value
        tasktime[0] = "Set time"

        taskList.delegate = self
        taskList.dataSource = self
    }
}

extension TaskListViewController: UITableViewDataSource {
    
    func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
        return taskCount
    }
    
    // Return custom cell + data to insert in table view
    func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell",for: indexPath) as! TaskCell
        
        cell.delegate = self
        
        // Configure nameField and timeButton in taskCell
        cell.nameField.text = taskName[indexPath.row]
        cell.timeButton.setTitle(tasktime[indexPath.row],for: .normal)
        
        return cell
    }
    
    func tableView(_ tableView: UITableView,commit editingStyle: UITableViewCell.EditingStyle,forRowAt indexPath: IndexPath) {

        // Update # of rows in taskList
        taskCount -= 1

        // Row that is deleted
        let deleteRowIndex = indexPath.row
        print(deleteRowIndex)

        // Remove taskName + tasktime from dictionary
        taskName[deleteRowIndex] = nil
        tasktime[deleteRowIndex] = nil

        // Delete row from table view
        let indexPaths = [indexPath]
        taskList.deleteRows(at: indexPaths,with: .fade)
        
        // Reload table view with new data
        taskList.reloadData()
    }
}

enter image description here

解决方法

在重新加载 tableView 之前,您必须在 commit editingStyle 方法中从 dataSource 数组中删除元素。更改后,您的方法将如下所示:

func tableView(_ tableView: UITableView,commit editingStyle: UITableViewCell.EditingStyle,forRowAt indexPath: IndexPath) {

    taskName.remove(at: indexPath.row) // remove element from array
    taskTime.remove(at: indexPath.row) // remove element from array

    // Delete row from table view
    taskList.deleteRows(at: [indexPath],with: .fade)
    
    // Reload table view with new data
    taskList.reloadData()
}
,
func tableView(_ tableView: UITableView,forRowAt indexPath: IndexPath) {

    // Remove taskName + taskTime from dictionary
    taskName.remove(at: indexPath.row) // remove element from array
    taskTime.remove(at: indexPath.row)

    // Delete row from table view
    taskList.deleteRows(at: [indexPath],with: .fade)
    
    // Reload table view with new data
    taskList.reloadData()
}
,

首先不要使用两个字典作为数据源使用一个数组自定义结构

struct Task {
    var name,time : String
}

var tasks = [Task]()

override func viewDidLoad() {
    super.viewDidLoad()
    
    // Set initial taskTime value
    tasks.append(Task(name:"",time: "Set time"))

    taskList.delegate = self
    taskList.dataSource = self
}

并且不要对单元格的数量进行硬编码,count 数组,taskCount 不是必需的。

extension TaskListViewController: UITableViewDataSource {
    
    func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
        return tasks.count
    }
    
    // Return custom cell + data to insert in table view
    func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell",for: indexPath) as! TaskCell
        
        cell.delegate = self
        
        // Configure nameField and timeButton in taskCell
        let task = tasks(indexPath.row)
        cell.nameField.text = task.name
        cell.timeButton.setTitle(task.time,for: .normal)
        
        return cell
    }

强烈建议使用 tableView(_:trailingSwipeActionsConfigurationForRowAt: 而不是 tableView(_:commit:forRowAt

在此方法中,删除给定索引路径处的项目并调用 deleteRows(at:with:)。在 reloadData() 之后立即调用 deleteRows(at:with:) 是多余的。后一种方法更新 UI

    override func tableView(_ tableView: UITableView,trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        
        let delete = UIContextualAction(style: .destructive,title: "Delete") { [unowned self] action,view,completionHandler in
            self.tasks.remove(at: indexPath.row) 
            tableView.deleteRows(at: [indexPath],with: .fade)
            completionHandler(true)
        }
        return UISwipeActionsConfiguration(actions: [delete])
    }
}

当然,您必须重构两个数据源字典的其他匹配项以匹配数据源数组。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。