Single and double taps on UITableViewCell in Swift

2019-04-13 18:00发布

问题:

I have storyboard segue on TableViewCell, which I use for transfering to another VC on cell click in didSelectRowAt method. Now I made double tap TapGestureRecognizer to handle touble tap on cell. Problem is that on single tap, segue is performing and double tap is not working. Double tap works fine with clicking out of cell. Is possible to solve this somehow with my code so far? Or I need to delete segue and handle single tap and double tap separately. Thanks for any suggestions

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let doubleTap = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
    doubleTap.numberOfTapsRequired = 2
    view.addGestureRecognizer(doubleTap)
}

func handleDoubleTap(recognizer: UIGestureRecognizer) {
    let p = recognizer.location(in: tableView)

    let indexPath = tableView.indexPathForRow(at: p)

    if let _ = indexPath {
        tableView.deselectRow(at: indexPath!, animated: true)
        update(index: (indexPath?.row)!, isFinished: true)
    }

    print ("doubke")
}


override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if (segue.identifier == "showSingleTask") {
        if let indexPath = tableView.indexPathForSelectedRow {
            let nav = segue.destination as! UINavigationController
            let destinationVC = nav.topViewController as! ShowTaskVC
            destinationVC.singleTask = tasks[indexPath.row]
        }
    }
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    tableView.deselectRow(at: indexPath as IndexPath, animated: true)
    self.selectedTask = tasks[indexPath.row]
}

回答1:

Details

xCode 8.3, Swift 3.1

Detect Double tap and Single tap on TableViewCell

ViewController.swift

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource = self
        tableView.tableFooterView = UIView()
    }
}

extension ViewController: UITableViewDataSource {

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
        cell.label.text = "\(indexPath)"
        cell.delegate = self
        return cell
    }
}

extension ViewController:TableViewCellDelegate {


    func tableViewCell(singleTapActionDelegatedFrom cell: TableViewCell) {
        let indexPath = tableView.indexPath(for: cell)
        print("singleTap \(String(describing: indexPath)) ")
    }

    func tableViewCell(doubleTapActionDelegatedFrom cell: TableViewCell) {
        let indexPath = tableView.indexPath(for: cell)
        print("doubleTap \(String(describing: indexPath)) ")
    }
}

TableViewCell.swift

import UIKit

class TableViewCell: UITableViewCell {

    @IBOutlet weak var label: UILabel!
    private var tapCounter = 0
    var delegate: TableViewCellDelegate?


    override func awakeFromNib() {
        super.awakeFromNib()

        let tap = UITapGestureRecognizer(target: self, action: #selector(tapAction))
        addGestureRecognizer(tap)
    }

    func tapAction() {

        if tapCounter == 0 {
            DispatchQueue.global(qos: .background).async {
                usleep(250000)
                if self.tapCounter > 1 {
                    self.doubleTapAction()
                } else {
                    self.singleTapAction()
                }
                self.tapCounter = 0
            }
        }
        tapCounter += 1
    }

    func singleTapAction() {
        delegate?.tableViewCell(singleTapActionDelegatedFrom: self)
    }

    func doubleTapAction() {
        delegate?.tableViewCell(doubleTapActionDelegatedFrom: self)
    }
}

TableViewCellDelegate.swift

import UIKit

protocol TableViewCellDelegate {
    func tableViewCell(singleTapActionDelegatedFrom cell: TableViewCell)
    func tableViewCell(doubleTapActionDelegatedFrom cell: TableViewCell)
}

Result