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

Swift中点击IQKeyboardManagerSwift的Done按钮获取TextField所在TableView的IndexPath

获取IQKeyboardManagerSwift Done按钮点击对应的TableView IndexPath

当然可以做到!作为Swift新手,遇到这种需要传递额外数据到回调的情况很常见,我给你几个实用的解决方案,帮你轻松拿到对应的IndexPath:

方案一:利用关联对象绑定IndexPath

这个方法通过Objective-C的关联对象特性,把IndexPath直接绑定到Done按钮上,简单直接:

首先定义一个关联键(放在类外面或者扩展里都可以):

private struct AssociatedKeys {
    static var indexPath = "indexPath"
}

然后修改你的cellForRowAt方法,绑定IndexPath到Done按钮:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "TimeSheetTableViewCell", for: indexPath) as? TimeSheetTableViewCell else {
        return UITableViewCell()
    }
    cell.txtTimeSheet.text = arrcheck[indexPath.row]
    
    // 绑定indexPath到done按钮
    let doneButton = cell.txtTimeSheet.keyboardToolbar.doneBarButton
    doneButton.setTarget(self, action: #selector(doneButtonClicked(_:)))
    objc_setAssociatedObject(doneButton, &AssociatedKeys.indexPath, indexPath, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    
    return cell
}

最后在回调方法里取出IndexPath:

@objc func doneButtonClicked(_ sender: UIBarButtonItem) {
    if let indexPath = objc_getAssociatedObject(sender, &AssociatedKeys.indexPath) as? IndexPath {
        print("Done clicked for row: \(indexPath.row)")
        // 在这里处理你需要的逻辑,比如更新数据源或做其他操作
    }
}

方案二:自定义Cell+闭包回调(推荐)

这个方案更符合Swift的面向对象风格,避免了Objective-C的黑魔法,代码可读性更高:

首先修改你的自定义Cell,添加IndexPath属性和闭包回调:

class TimeSheetTableViewCell: UITableViewCell {
    @IBOutlet weak var txtTimeSheet: UITextField! // 或UITextView,根据你的实际情况
    var indexPath: IndexPath?
    var onDoneButtonTapped: ((IndexPath) -> Void)?
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // 把Done按钮的点击事件绑定到cell内部的方法
        txtTimeSheet.keyboardToolbar.doneBarButton.setTarget(self, action: #selector(doneButtonTapped))
    }
    
    @objc private func doneButtonTapped() {
        guard let indexPath = indexPath else { return }
        onDoneButtonTapped?(indexPath)
    }
}

然后在cellForRowAt中设置闭包:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "TimeSheetTableViewCell", for: indexPath) as? TimeSheetTableViewCell else {
        return UITableViewCell()
    }
    cell.txtTimeSheet.text = arrcheck[indexPath.row]
    cell.indexPath = indexPath
    
    // 设置闭包回调
    cell.onDoneButtonTapped = { [weak self] tappedIndexPath in
        guard let self = self else { return }
        print("Done clicked for row: \(tappedIndexPath.row)")
        // 在这里处理你的业务逻辑
    }
    
    return cell
}

这个方案不需要修改原来的doneButtonClicked方法,逻辑都封装在cell和闭包里,更清晰。

方案三:通过视图层级查找Cell(不推荐)

这个方法通过找到当前编辑的文本框,再递归查找它所在的Cell,最后获取IndexPath。不过缺点是依赖视图层级,如果你的Cell布局变化,可能会失效:

@objc func doneButtonClicked(_ sender: Any) {
    // 找到当前第一响应者的文本框/文本视图
    guard let textField = UIResponder.currentFirst() as? UITextField else { return }
    
    // 递归查找父视图中的Cell
    func findParentCell(_ view: UIView) -> TimeSheetTableViewCell? {
        if let cell = view as? TimeSheetTableViewCell {
            return cell
        }
        return view.superview != nil ? findParentCell(view.superview!) : nil
    }
    
    guard let targetCell = findParentCell(textField),
          let indexPath = tableView.indexPath(for: targetCell) else { return }
    
    print("Done clicked for row: \(indexPath.row)")
}

个人更推荐方案二,代码更易维护,也更符合Swift的编程习惯。

内容的提问来源于stack exchange,提问作者Muju

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 18:12:42