如何向 UITableViewCell 添加手势?
Posted
技术标签:
【中文标题】如何向 UITableViewCell 添加手势?【英文标题】:How to add gesture to UITableViewCell? 【发布时间】:2016-06-08 03:57:55 【问题描述】:我想为 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 上添加 UIButton,每个按钮都有唯一的标签号。为按钮分配一种方法。您可以在该方法上获取标签号 【参考方案1】:要给 UITableViewCell 添加手势,可以按照以下步骤操作:
首先,给 UITableView 添加手势识别器
tapGesture = UITapGestureRecognizer(target: self, action: #selector(tableViewController.tapEdit(_:)))
tableView.addGestureRecognizer(tapGesture!)
tapGesture!.delegate = self
然后,定义选择器。使用recognizer.locationInView
定位您在tableView 中点击的单元格。你可以通过tapIndexPath
访问你的dataSource中的数据,这是用户点击的单元格的indexPath。
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()
在您的 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
但是,此方法可能会导致问题,请参阅UIGestureRecognizer and UITableViewCell issue。在这种情况下,当滑动手势成功时,选择器会因为某种原因被调用两次。我不能说第二种方法不好,因为我还没有找到任何直接证据,但是通过谷歌搜索后,似乎第一种方法是标准方法。
【讨论】:
将手势添加到 tableViewCell 而不是 tableView 似乎很自然,然后在代码中指定哪个。对于像平移这样更复杂的手势,编写条件检查平移是否在单元格中开始/停留/结束并处理其他情况对我来说可能很痛苦。我想给 tableviewcell 添加手势,在 tableviewcell.swift 中编写代码。是否可以?你能回答我的第二个问题,我如何编写 UITapGestureRecognizer(target, action) 的目标和选择器 目标和选择器let tapGesture = UITapGestureRecognizer(target: self, action: #selector(MyTableViewCell.tapEdit(_:)))
让 tapGesture = UITapGestureRecognizer(target: self, action: #selector(MyTableViewCell.tapEdit(_:))) 工作。但在我的情况下,手势与数据源交互,所以我希望目标是 UITableViewController,并使用其中一个函数(可以改变数据源),怎么做?
谢谢,它有效。出于好奇,目标只能是自我(或属于类的东西)?
@FateRiddle No. target 是一个对象,它是接收者在表示的手势发生时发送的动作消息的接收者。您可以多次调用此方法来指定多个目标-动作对。但是,如果您请求添加已添加的目标-操作对,则该请求将被忽略。 “self”这里是你的自定义单元格【参考方案2】:
你不需要添加手势识别器来实现你正在做的事情。
使用UITableViewDelegate
方法tableView:didSelectRowAtIndexPath:
检测哪一行被点击(这正是你的tapGesture
要做的事情),然后进行你想要的处理。
如果您不喜欢选择单元格时的灰色指示,请在返回单元格之前在您的tableView:didEndDisplayingCell:forRowAtIndexPath:
中键入:cell?.selectionStyle = .None
【讨论】:
点击只是一个例子,我喜欢在每个单元格上做各种手势。 你有自定义的单元格类吗? 如果是,则在自定义单元格类的awakeFromNib
方法中添加手势识别器
我就是这么做的,但我不知道如何编写一个使用 TableViewController 中的函数的 UITapGestureRecognizer。如果代码在 myTableViewCell.swift 中的 awakeFromNib 中【参考方案3】:
在 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")
【讨论】:
实例成员“addGestureRecognizer”不能用于类型“TestViewCell”【参考方案4】:最简单的方法是在自定义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
【讨论】:
以上是关于如何向 UITableViewCell 添加手势?的主要内容,如果未能解决你的问题,请参考以下文章
在 UITableViewCell 的子视图上添加单击和双击手势