Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/114.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 带操作的UITableViewCell按钮_Ios_Swift_Uitableview_Uibutton_Swift3 - Fatal编程技术网

Ios 带操作的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,它有三个按钮来处理购物车功能,加、减和删除按钮,我需要知道哪个单元格被触摸过

我已经尝试过使用“标签解决方案”,但由于电池的生命周期,它不起作用

有人能帮我找到解决办法吗


提前感谢

我使用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视图的层次结构获取所选按钮索引

使用以下步骤:

  • 将选择器添加到tableview的cellForRowAtIndexpath:

    btn?.addTarget(self, action:#selector(buttonPressed(_:)), for:.touchUpInside)
    
  • 二,。使用以下方法获取indexPath:

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