You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击导航栏编辑按钮时,如何启用TableViewCell中TextField的编辑权限

解决导航栏Edit按钮切换TableViewCell TextField编辑状态(含复用同步)的问题

我懂你的需求:点击导航栏右上角的Edit按钮,要让TableViewCell里的TextField从不可编辑切换为可编辑状态,而且当数组元素较多、滚动屏幕后,之前不在视野里的cell也要同步这个编辑权限。下面是完整的解决方案,已经处理了UITableView cell复用带来的状态不一致问题:

核心解决思路

  1. 依托TableView编辑状态统一管控:因为UITableView的cell是复用机制,只修改当前可见的cell肯定不行,必须在cellForRowAt方法里根据tableView.isEditing来设置textField的isEnabled属性,这样滚动时新出现的复用cell会自动应用正确的状态。
  2. 自定义Edit/Done按钮交互:系统默认的editButtonItem不好自定义状态切换后的文字,所以我们自己创建导航栏按钮,点击时切换tableView的编辑状态,同时更新所有可见cell的textField状态,顺便切换按钮的文字和样式。
  3. 把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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:23:49