UITableView是iOS开发中用于显示列表数据的核心组件,删除行是常见的交互操作。删除操作通常涉及数据源更新和界面刷新两个步骤。
// 1. 实现tableView(_:commit:forRowAt:)方法
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// 2. 先删除数据源中的数据
dataArray.remove(at: indexPath.row)
// 3. 再删除表格中的行
tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
var dataArray = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
// MARK: - UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = dataArray[indexPath.row]
return cell
}
// 启用行编辑
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
// 处理删除操作
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// 先删除数据源
dataArray.remove(at: indexPath.row)
// 再删除行
tableView.deleteRows(at: [indexPath], with: .fade)
// 或者使用reloadData(),但动画效果较差
// tableView.reloadData()
}
}
// 自定义删除按钮文字
func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
return "删除"
}
}
import UIKit
class DiffableDataSourceViewController: UIViewController {
enum Section {
case main
}
@IBOutlet weak var tableView: UITableView!
var dataSource: UITableViewDiffableDataSource<Section, String>!
var items = ["Apple", "Banana", "Orange", "Pear", "Grape"]
override func viewDidLoad() {
super.viewDidLoad()
configureDataSource()
applyInitialSnapshot()
}
func configureDataSource() {
dataSource = UITableViewDiffableDataSource<Section, String>(tableView: tableView) {
(tableView: UITableView, indexPath: IndexPath, item: String) -> UITableViewCell? in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = item
return cell
}
dataSource.defaultRowAnimation = .fade
}
func applyInitialSnapshot() {
var snapshot = NSDiffableDataSourceSnapshot<Section, String>()
snapshot.appendSections([.main])
snapshot.appendItems(items)
dataSource.apply(snapshot, animatingDifferences: true)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// 获取当前项
guard let itemToDelete = dataSource.itemIdentifier(for: indexPath) else { return }
// 更新数据源
if let index = items.firstIndex(of: itemToDelete) {
items.remove(at: index)
}
// 应用新的快照
var snapshot = dataSource.snapshot()
snapshot.deleteItems([itemToDelete])
dataSource.apply(snapshot, animatingDifferences: true)
}
}
}
原因: 数据源和表格视图不同步,通常是在调用deleteRows(at:with:)
之前没有正确更新数据源。
解决方案:
numberOfRowsInSection
返回的值是否正确reloadData()
作为临时解决方案原因:
tableView(_:canEditRowAt:)
方法或返回了falseUITableViewDelegate
解决方案:
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: "删除") { (action, view, completionHandler) in
// 删除操作
self.dataArray.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
completionHandler(true)
}
deleteAction.backgroundColor = .systemRed
deleteAction.image = UIImage(systemName: "trash")
let configuration = UISwipeActionsConfiguration(actions: [deleteAction])
configuration.performsFirstActionWithFullSwipe = false // 完全滑动时不自动执行第一个操作
return configuration
}
没有搜到相关的文章