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
相关产品推荐
相关产品推荐

