ios 如何向 UITableViewCell 添加手势?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37692978/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to add gesture to UITableViewCell?
提问by Fate Riddle
I want to add a tap gesture to every cell in a UITableView
that edits the content in it. The two ways to add a gesture are in code or through storyboard. I tried both and they failed.
我想为 a 中的每个单元格添加一个点击手势来UITableView
编辑其中的内容。添加手势的两种方法是在代码中或通过故事板。我两个都试过了,都失败了。
Can I add a gesture to everycell in table with storyboard drag and drop? It seems to only add gesture to the first cell. Adding gesture in code, I wrote something like,
我可以通过情节提要拖放向表格中的每个单元格添加手势吗?它似乎只向第一个单元格添加手势。在代码中添加手势,我写了一些类似的东西,
addGestureRecognizer(UITapGestureRecognizer(target: self,action:#selector(MyTableViewCell.tapEdit(_:))))
or
或者
addGestureRecognizer(UITapGestureRecognizer(target: self, action:"tapEdit:"))
both work. But I'd like to let the UITableViewController
handle this gesture because it does something with the datasource. How do I write my target and action?
两者都工作。但我想让UITableViewController
处理这个手势,因为它对数据源做了一些事情。我如何写我的目标和行动?
EDIT:
编辑:
addGestureRecognizer(UITapGestureRecognizer(target: MasterTableViewController.self, action:#selector(MasterTableViewController.newTapEdit(_:)))
it induce an error said, unrecognized selector sent to class 0x106e674e0...
它引发了一个错误说,无法识别的选择器发送到类 0x106e674e0 ...
回答by ilovecomputer
To add gesture to UITableViewCell, you can follow the steps below:
要为 UITableViewCell 添加手势,您可以按照以下步骤操作:
First, add gesture recognizer to UITableView
首先,给 UITableView 添加手势识别器
tapGesture = UITapGestureRecognizer(target: self, action: #selector(tableViewController.tapEdit(_:)))
tableView.addGestureRecognizer(tapGesture!)
tapGesture!.delegate = self
Then, define the selector. Use recognizer.locationInView
to locate the cell you tap in tableView. And you can access the data in your dataSource by tapIndexPath
, which is the indexPath of the cell the user tapped.
然后,定义选择器。使用recognizer.locationInView
找到你的tableView轻按细胞。您可以通过 访问 dataSource 中的数据tapIndexPath
,这是用户点击的单元格的 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
}
}
}
}
It is possible to add gesture directly to TableView cell and access the datasource in viewController, You need to set up a delegate:
可以直接向TableView单元格添加手势并访问viewController中的数据源,您需要设置一个委托:
In your custom cell:
在您的自定义单元格中:
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()
}
In your 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
}
}
However, this method could cause problems, see UIGestureRecognizer and UITableViewCell issue. In this case, when the swipe gesture successes, the selector get called twice for some reason. I can't say the second method is a bad one as I haven't found any direct evidence yet, but after searching through Google, it seems like the first method is the standard way.
但是,此方法可能会导致问题,请参阅UIGestureRecognizer 和 UITableViewCell 问题。在这种情况下,当滑动手势成功时,选择器由于某种原因被调用两次。我不能说第二种方法不好,因为我还没有找到任何直接的证据,但是通过谷歌搜索后,第一种方法似乎是标准方法。
回答by Rohan Sanap
You don't need to add gesture recognizer to achieve what you are doing.
您不需要添加手势识别器来实现您正在做的事情。
- Use the
UITableViewDelegate
methodtableView:didSelectRowAtIndexPath:
to detect which row is tapped (this is what exactly yourtapGesture
is going to do) and then do your desired processing. - If you don't like the gray indication when you select cell, type this in your
tableView:didEndDisplayingCell:forRowAtIndexPath:
just before returning the cell:cell?.selectionStyle = .None
- 使用该
UITableViewDelegate
方法tableView:didSelectRowAtIndexPath:
检测哪一行被点击(这正是您tapGesture
要执行的操作),然后进行所需的处理。 - 如果您不喜欢选择单元格时的灰色指示,请
tableView:didEndDisplayingCell:forRowAtIndexPath:
在返回单元格之前输入以下内容:cell?.selectionStyle = .None
回答by LembergSun
Adding gesture in awakeFromNib method seems much more easier and works fine.
在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")
}
}
回答by skmalm
The easiest way to do this is to add the gesture in a custom UITableViewCell
. An easier alternative to setting up a custom delegate pattern is to inform the view controller of the edits would be to use a handler in the form of a closure that the view controller can provide and which is called when user editing is finished. I'm assuming a textField is used to allow cell editing.
最简单的方法是在自定义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?()
}
}
And within your custom UITableViewController
, pass in the handler to be able to make changes to your model. Don't forget to account for possible memory cycles in the closure.
在您的 custom 中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
}