Ios 带操作的UITableViewCell按钮
嗨,我有一个自定义的UITableViewCell,它有三个按钮来处理购物车功能,加、减和删除按钮,我需要知道哪个单元格被触摸过 我已经尝试过使用“标签解决方案”,但由于电池的生命周期,它不起作用 有人能帮我找到解决办法吗Ios 带操作的UITableViewCell按钮,ios,swift,uitableview,uibutton,swift3,Ios,Swift,Uitableview,Uibutton,Swift3,嗨,我有一个自定义的UITableViewCell,它有三个按钮来处理购物车功能,加、减和删除按钮,我需要知道哪个单元格被触摸过 我已经尝试过使用“标签解决方案”,但由于电池的生命周期,它不起作用 有人能帮我找到解决办法吗 提前感谢我使用UITableViewCell子类中的cell委托方法解决了这个问题 快速概述: 1)创建协议 protocol YourCellDelegate : class { func didPressButton(_ tag: Int) } 2)子类您的UI
提前感谢我使用UITableViewCell子类中的cell委托方法解决了这个问题 快速概述: 1)创建协议
protocol YourCellDelegate : class {
func didPressButton(_ tag: Int)
}
2)子类您的UITableViewCell
(如果您尚未这样做):
3)让您的视图控制器符合上面实现的YourCellDelegate
协议
class YourViewController: ..., YourCellDelegate { ... }
4)定义单元格后(用于重用),设置委托
5)在同一控制器中(您的UITableView委托/数据源在哪里),放置来自YourCellDelegate
协议的方法
func didPressButton(_ tag: Int) {
print("I have pressed a button with a tag: \(tag)")
}
现在,您的解决方案不依赖于标签/编号。您可以根据需要添加任意多个按钮,这样无论要安装多少个按钮,都可以通过委托获得响应
此协议委托解决方案在iOS逻辑中是首选方案,它可以用于表单元格中的其他元素,如
UISwitch
、UIStepper
,等等。您还可以使用tableViewCell视图的层次结构获取所选按钮索引
使用以下步骤:
btn?.addTarget(self, action:#selector(buttonPressed(_:)), for:.touchUpInside)
func buttonPressed(_ sender: AnyObject) {
let button = sender as? UIButton
let cell = button?.superview?.superview as? UITableViewCell
let indexPath = tblview.indexPath(for: cell!)
print(indexPath?.row)
}
正如社区广泛建议的那样,我在将iboutlet私有化后遇到了同样的问题 以下是我的解决方案: <在您的手机类中>
protocol YourCellDelegate: class {
func didTapButton(_ sender: UIButton)
}
class YourCell: UITableViewCell {
weak var delegate: YourCellDelegate?
@IBAction func buttonTapped(_ sender: UIButton) {
delegate?.didTapButton(sender)
}
}
<在您的ViewController中>
class ViewController: UIViewController, YourCellDelegate {
func didTapButton(_ sender: UIButton) {
if let indexPath = getCurrentCellIndexPath(sender) {
item = items[indexPath.row]
}
}
func getCurrentCellIndexPath(_ sender: UIButton) -> IndexPath? {
let buttonPosition = sender.convert(CGPoint.zero, to: tableView)
if let indexPath: IndexPath = tableView.indexPathForRow(at: buttonPosition) {
return indexPath
}
return nil
}
}
SWIFT 4.* 它也可以像下面这样做,不需要太多的编码和授权,简单易行 将以下代码放入
UICollectionView的cellForItemAt
或UITableView的cellForRowAt
中
cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: #selector(buttonSelected), for: .touchUpInside)
你的方法是
@objc func buttonSelected(sender: UIButton){
print(sender.tag)
}
仅此而已。@pedrouan很棒,除了使用button的标签
选项。在许多情况下,当您在tableViewCell
上设置按钮时,这些按钮将修改tableView数据源(例如InsertRow、DeleteRow)
但是,即使插入了新单元格
或删除了新单元格
,按钮的标签也不会更新。因此,最好将单元格
本身作为参数传递,而不是将按钮的标记
传递给参数
下面是我实现这一目标的示例
您的ExampleCell
protocol ExampleCellDelegate: class {
func didTapButton(cell: ExampleCell)
}
class ExampleCell: UITableViewCell {
weak var cellDelegate: ExampleCellDelegate?
@IBAction func btnTapped(_ sender: UIButton) {
cellDelegate?.didTapButton(cell: self)
}
}
您的ViewController
class ViewController: ExampleCellDelegate {
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "ExampleCell", for: indexPath) as? ExampleCell {
cell.cellDelegate = self
return cell
}
return UITableViewCell()
}
func didTapButton(cell: ExampleCell) {
if let indexPath = tableView.indexPath(for: cell) {
// do Something
}
}
}
“Tableview”单元格中的UIButton。在swift 4.2中以编程方式创建动作方法
cell.btnlike.addTarget(self, action: #selector(buttonbtnlikePressed(_:event:)), for: .touchUpInside)
@objc func buttonbtnlikePressed(_ sender: Any, event: Any) {
let point : CGPoint = (sender as AnyObject).convert(CGPoint.zero, to:tblPost)
var indexPath = self.tblPost!.indexPathForRow(at: point)
if let btnlike = sender as? UIButton{
if btnlike.isSelected{
btnlike.isSelected = false
}else{
btnlike.isSelected = true
}
}
}
swift 4.2 也可以使用闭包而不是委托 1) 在UITableViewCell中:
class ExampleCell: UITableViewCell {
//create your closure here
var buttonPressed : (() -> ()) = {}
@IBAction func buttonAction(_ sender: UIButton) {
//Call your closure here
buttonPressed()
}
}
2) 在ViewController中
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ExampleCell", for: indexPath) as! ExampleCell
cell.buttonPressed = {
//Code
}
return cell
}
}
请提供一些代码,说明您如何准确地使用标记。如果每次重复使用单元格时都将它们设置在CellForRowatineXpath中,则生命周期不会出现任何问题。此解决方案看起来很神奇,但我仍需要知道我按下了哪个单元格,当使用tag参数时,问题仍然是相同的。您可能只需要在单元格中的按钮和步骤2中键入的IBAction buttonPressed()方法之间添加一个连接。2)cell.tag=indexPath.row仅为所有行提供0。步骤2中的sender.tag不应该是self.tag,因为它是您在步骤4中设置为indexPath.row的单元格标记。在步骤2中使用self.tag而不是sender.tag对我来说是正常的。如果tableview也实现了节,如何解析单元格索引路径的节部分?若要处理多个节,请为单元格指定一个indexPath变量并设置该变量,而不是使用标记。您的解决方案应该是可接受的。当将单元格的按钮配置为绑定到视图控制器的操作时,它也可以在不使用UITableViewCell子类的委派模式的情况下工作。不使用.tag属性和更干净的方式更好!另一种代替转换点的方法是使用superview获取单元格,然后调用
indexPath(for:UITableViewCell)
您忘记了cell.delegate=self在CellForRowatineIndexPath中。谢谢@Deyaelden-这是唯一需要的其他东西。这是一个很好的解决方案,但与视图的设计方式密切相关。如果按钮位于另一个子视图(例如堆栈视图),您可能会得到一长串superview调用来检测按钮所在的单元格。这是包含最佳实践的唯一正确答案,这很有趣,因为它没有向上投票。只需查看UITableViewDelegate之类的示例即可获得指导。您应该在委托方法中传递单元格本身。然后,例如,在控制器中,可以获取单元格的索引路径,然后可以使用该路径通过indexath.row访问数据源中的正确数据。依赖一个像原始标记一样的标记是没有意义的,而且注定会失败。感谢@RimK它的工作正常+1 up提供了这个解决方案
class ExampleCell: UITableViewCell {
//create your closure here
var buttonPressed : (() -> ()) = {}
@IBAction func buttonAction(_ sender: UIButton) {
//Call your closure here
buttonPressed()
}
}
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ExampleCell", for: indexPath) as! ExampleCell
cell.buttonPressed = {
//Code
}
return cell
}
}