如何向UITableViewCell添加手势?

时间:2016-06-08 03:57:56

标签: ios swift uitableview uigesturerecognizer

我想为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 ...

5 个答案:

答案 0 :(得分:35)

要向UITableViewCell添加手势,您可以按照以下步骤操作:

首先,将手势识别器添加到UITableView

tapGesture = UITapGestureRecognizer(target: self, action: #selector(tableViewController.tapEdit(_:)))
tableView.addGestureRecognizer(tapGesture!)
tapGesture!.delegate = self

然后,定义选择器。使用recognizer.locationInView找到您在tableView中点按的单元格。您可以通过tapIndexPath访问dataSource中的数据,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 } } } } 是用户点击的单元格的indexPath。

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() 
}

可以直接向TableView单元添加手势并访问viewController中的数据源,您需要设置一个委托:

在您的自定义单元格中:

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
    }

}

在您的viewController中:

{{1}}

但是,此方法可能会导致问题,请参阅UIGestureRecognizer and UITableViewCell issue。在这种情况下,当滑动手势成功时,由于某种原因选择器被调用两次。我不能说第二种方法是坏的,因为我还没有找到任何直接证据,但在搜索谷歌之后,似乎第一种方法是标准方法。

答案 1 :(得分:5)

您无需添加手势识别器即可实现您的目标。

  • 使用UITableViewDelegate方法tableView:didSelectRowAtIndexPath:来检测点击的行(这就是您的tapGesture将要执行的操作)然后执行您想要的操作处理
  • 如果您在选择单元格时不喜欢灰色指示,请在返回单元格之前在tableView:didEndDisplayingCell:forRowAtIndexPath:中键入此内容:
    cell?.selectionStyle = .None

答案 2 :(得分:2)

在awakeFromNib方法中添加手势似乎更容易并且可以正常工作。

class TestCell: UITableViewCell {

    override func awakeFromNib() {
        super.awakeFromNib()

        let panGesture = UIPanGestureRecognizer(target: self,
                                            action: #selector(gestureAction))
        addGestureRecognizer(panGesture)
    }

    @objc func gestureAction() {
        print("gesture action")
    }
}

答案 3 :(得分:0)

最简单的方法是在自定义UITableViewCell中添加手势。设置自定义委托模式的一种更简单的替代方法是通知视图控制器有关编辑的操作,即使用视图控制器可以提供的闭包形式的处理程序,并在用户编辑完成时调用该处理程序。我假设使用textField允许单元格编辑。

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
}

答案 4 :(得分:-3)

在CellForRowAtIndexPath中,返回单元格之前。创建点击手势并设置为单元格。