如何在 Table 视图中 swipe-to-delete 使用自定义 Table 视图单元格?
How to swipe-to-delete in a TableView with custom Table View cells?
目前,我有一个屏幕显示带有自定义单元格的 TableView,每个单元格都有一个文本字段和一个按钮。我将文本字段的数据输入存储到 taskName dict 中,并将按钮的标题选择(从 pop-up 屏幕)存储到 taskTime dict 中。
但是,我的问题是当我 swipe-to-delete 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()
}
}
在重新加载 tableView 之前,您必须在 commit editingStyle
方法中从数据源数组中删除元素。更改后您的方法将如下所示:
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,
commit editingStyle: UITableViewCell.EditingStyle,
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:)
。在 deleteRows(at:with:)
之后立即调用 reloadData()
是多余的。后一种方法更新 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])
}
}
当然你必须重构两个数据源字典的其他出现以匹配数据源数组。
目前,我有一个屏幕显示带有自定义单元格的 TableView,每个单元格都有一个文本字段和一个按钮。我将文本字段的数据输入存储到 taskName dict 中,并将按钮的标题选择(从 pop-up 屏幕)存储到 taskTime dict 中。
但是,我的问题是当我 swipe-to-delete 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()
}
}
在重新加载 tableView 之前,您必须在 commit editingStyle
方法中从数据源数组中删除元素。更改后您的方法将如下所示:
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,
commit editingStyle: UITableViewCell.EditingStyle,
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:)
。在 deleteRows(at:with:)
之后立即调用 reloadData()
是多余的。后一种方法更新 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])
}
}
当然你必须重构两个数据源字典的其他出现以匹配数据源数组。