我想向
UITableView
中的每个单元格添加点击手势,以编辑其中的内容。添加手势的两种方法是通过代码或通过情节提要。我都尝试过,但都失败了。
我可以通过故事板拖放向表格中的每个单元格添加手势吗?它似乎只向第一个单元格添加手势。在代码中添加手势,我写了类似的东西,
addGestureRecognizer(UITapGestureRecognizer(target: self,action:#selector(MyTableViewCell.tapEdit(_:))))
或
addGestureRecognizer(UITapGestureRecognizer(target: self, action:"tapEdit:"))
两者都有效。但我想让
UITableViewController
处理这个手势,因为它对数据源做了一些事情。我如何写出我的目标和行动?
编辑:
addGestureRecognizer(UITapGestureRecognizer(target: MasterTableViewController.self, action:#selector(MasterTableViewController.newTapEdit(_:)))
它会引发错误,无法识别的选择器发送到类 0x106e674e0...
要向 UITableViewCell 添加手势,可以按照以下步骤操作:
首先,向 UITableView 添加手势识别器
tapGesture = UITapGestureRecognizer(target: self, action: #selector(tableViewController.tapEdit(_:)))
tableView.addGestureRecognizer(tapGesture!)
tapGesture!.delegate = self
然后,定义选择器。使用
recognizer.locationInView
定位您在 tableView 中点击的单元格。您可以通过 tapIndexPath
访问数据源中的数据,这是用户点击的单元格的索引路径。
func tapEdit(recognizer: UITapGestureRecognizer) {
if recognizer.state == UIGestureRecognizerState.Ended {
let tapLocation = recognizer.locationInView(self.tableView)
if let tapIndexPath = self.tableView.indexPathForRowAtPoint(tapLocation) {
if let tappedCell = self.tableView.cellForRowAtIndexPath(tapIndexPath) as? MyTableViewCell {
//do what you want to cell here
}
}
}
}
可以直接向TableView单元添加手势并访问viewController中的数据源,您需要设置一个委托:
在您的自定义单元格中:
import UIKit
class MyTableViewCell: UITableViewCell {
var delegate: myTableDelegate?
override func awakeFromNib() {
super.awakeFromNib()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(MyTableViewCell.tapEdit(_:)))
addGestureRecognizer(tapGesture)
//tapGesture.delegate = ViewController()
}
func tapEdit(sender: UITapGestureRecognizer) {
delegate?.myTableDelegate()
}
}
protocol myTableDelegate {
func myTableDelegate()
}
在你的视图控制器中:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIGestureRecognizerDelegate, myTableDelegate {
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 35
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as? MyTableViewCell
cell?.delegate = self
return cell!
}
func myTableDelegate() {
print("tapped")
//modify your datasource here
}
}
但是,此方法可能会导致问题,请参阅UIGestureRecognizer 和 UITableViewCell 问题。在这种情况下,当滑动手势成功时,由于某种原因,选择器会被调用两次。我不能说第二种方法不好,因为我还没有找到任何直接证据,但通过谷歌搜索后,似乎第一种方法是标准方法。
您不需要添加手势识别器来实现您正在做的事情。
UITableViewDelegate
方法 tableView:didSelectRowAtIndexPath:
检测哪一行被点击(这正是您的 tapGesture
要做的事情),然后进行所需的处理。tableView:didEndDisplayingCell:forRowAtIndexPath:
中输入以下内容:cell?.selectionStyle = .None
对于单元格,您只需在
awakeFromNib
中添加手势即可:
class TestCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
let g = UIPanGestureRecognizer(target: self, action: #selector(pan))
addGestureRecognizer(g)
}
@objc func pan() {
print("gesture action")
}
}
最简单的方法是在自定义中添加手势
UITableViewCell
。设置自定义委托模式的一种更简单的替代方法是通知视图控制器编辑情况,即使用视图控制器可以提供的闭包形式的处理程序,并在用户编辑完成时调用该处理程序。我假设文本字段用于允许单元格编辑。
class CustomTableViewCell: UITableViewCell {
func activateTitleEditing() {
textField.isEnabled = true
textField.becomeFirstResponder()
}
// This will hold the handler closure which the view controller provides
var resignationHandler: (() -> Void)?
@objc private func tap(_ recognizer: UITapGestureRecognizer) {
guard recognizer.state == .ended else { return }
activateTitleEditing()
}
@IBOutlet weak var textField: UITextField! { didSet {
textField.delegate = self
let tap = UITapGestureRecognizer(target: self, action: #selector(tap(_:)))
addGestureRecognizer(tap)
textField.isEnabled = false
}}
}
extension CustomTableViewCell: UITextFieldDelegate {
func textFieldDidEndEditing(_ textField: UITextField) {
resignationHandler?()
}
}
并在您的自定义
UITableViewController
中,传入处理程序以便能够对模型进行更改。不要忘记考虑闭包中可能的内存周期。
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// initialize and return table view cell
let cell = tableView.dequeueReusableCell(withIdentifier: K.documentCellIdentifier, for: indexPath)
assert(cell is CustomTableViewCell, "Document cell dequeuing error")
let customCell = cell as! DocumentTableViewCell
customCell.textField.text = documentModel.documents[indexPath.row]
customCell.resignationHandler = { [weak self, unowned customCell] in
guard let self = self else { return }
if let newTitle = customCell.textField.text {
self.cellModel.cells[indexPath.row] = newTitle
}
}
return customCell
}