点击导航栏编辑按钮时,如何启用TableViewCell中TextField的编辑权限
解决导航栏Edit按钮切换TableViewCell TextField编辑状态(含复用同步)的问题
我懂你的需求:点击导航栏右上角的Edit按钮,要让TableViewCell里的TextField从不可编辑切换为可编辑状态,而且当数组元素较多、滚动屏幕后,之前不在视野里的cell也要同步这个编辑权限。下面是完整的解决方案,已经处理了UITableView cell复用带来的状态不一致问题:
核心解决思路
- 依托TableView编辑状态统一管控:因为UITableView的cell是复用机制,只修改当前可见的cell肯定不行,必须在
cellForRowAt方法里根据tableView.isEditing来设置textField的isEnabled属性,这样滚动时新出现的复用cell会自动应用正确的状态。 - 自定义Edit/Done按钮交互:系统默认的
editButtonItem不好自定义状态切换后的文字,所以我们自己创建导航栏按钮,点击时切换tableView的编辑状态,同时更新所有可见cell的textField状态,顺便切换按钮的文字和样式。 - 把TextField状态控制权上移:移除TableViewCell里初始的
textField.isEnabled = false,让TableViewController统一管理这个状态,避免出现局部状态不一致的情况。
最终代码
TableViewController.swift
import UIKit class TableViewController: UITableViewController, TableViewCellDelegate { @IBOutlet var ttableView: UITableView! // 测试用的20个元素数组 var array:[String] = ["aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo", "ppp", "qqq", "rrr", "sss", "ttt"] override func viewDidLoad() { super.viewDidLoad() // 自定义导航栏右侧按钮,替换系统默认的editButtonItem navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Edit", style: .plain, target: self, action: #selector(rightBarButtonItemTapped)) } // 处理导航栏按钮点击事件 @objc func rightBarButtonItemTapped(_ sender: UIBarButtonItem) { // 切换tableView的编辑状态 ttableView.setEditing(!ttableView.isEditing, animated: true) // 更新按钮的文字和样式 navigationItem.rightBarButtonItem?.title = ttableView.isEditing ? "Done" : "Edit" navigationItem.rightBarButtonItem?.style = ttableView.isEditing ? .done : .plain // 更新当前所有可见cell的textField状态 ttableView.visibleCells.forEach { cell in guard let inputCell = cell as? TableViewCell else { return } inputCell.textField.isEnabled = ttableView.isEditing } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } // MARK: - Table view data source override func numberOfSections(in tableView: UITableView) -> Int { return 1 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return array.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "inputCell", for: indexPath) as! TableViewCell cell.textField.text = array[indexPath.row] // 根据tableView的编辑状态设置textField是否可编辑,解决复用问题 cell.textField.isEnabled = tableView.isEditing cell.delegate = self return cell } // MARK: - TableViewCellDelegate func textFieldDidEndEditing(cell: TableViewCell, value: String) { guard let indexPath = tableView.indexPathForRow(at: cell.convert(cell.bounds.origin, to: tableView)) else { return } array[indexPath.row] = value } // MARK: - TableView编辑相关 override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { array.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .fade) } } override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle { return tableView.isEditing ? .delete : .none } override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { guard let cell = tableView.cellForRow(at: sourceIndexPath) as? TableViewCell, let moveData = cell.textField.text else { return } array.remove(at: sourceIndexPath.row) array.insert(moveData, at: destinationIndexPath.row) } }
TableViewCell.swift
import UIKit protocol TableViewCellDelegate { func textFieldDidEndEditing(cell: TableViewCell, value: String) } class TableViewCell: UITableViewCell, UITextFieldDelegate { var delegate: TableViewCellDelegate! @IBOutlet weak var textField: UITextField! override func awakeFromNib() { super.awakeFromNib() textField.delegate = self textField.returnKeyType = .done // 移除初始的禁用设置,状态由TableViewController统一管理 } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) } // MARK: - UITextFieldDelegate func textFieldDidEndEditing(_ textField: UITextField) { guard let text = textField.text else { return } delegate.textFieldDidEndEditing(cell: self, value: text) } func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true } }
内容的提问来源于stack exchange,提问作者TakeYourMark
相关产品推荐
相关产品推荐

