【问题标题】:UIButton action in table view cell表格视图单元格中的 UIButton 操作
【发布时间】:2015-05-07 19:41:49
【问题描述】:

我正在尝试为在表格视图单元格中按下的按钮运行一个动作。以下代码在我的表视图控制器类中。

在我的 UITableViewCell 类中名为 requestsCell 的插座中,该按钮被描述为“是”。

我正在使用 Parse 保存数据,并希望在按下按钮时更新对象。我的 objectIds 数组工作正常, cell.yes.tag 还会将正确的数字打印到日志中,但是,我无法将该数字输入“已连接”函数以正确运行我的查询。

我需要一种方法来获取单元格的 indexPath.row 以找到正确的 objectId。

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as requestsCell

    // Configure the cell...

    cell.name.text = requested[indexPath.row]

    imageFiles[indexPath.row].getDataInBackgroundWithBlock{
        (imageData: NSData!, error: NSError!) -> Void in

        if error == nil {

            let image = UIImage(data: imageData)

            cell.userImage.image = image
        }else{
            println("not working")
        }    
    }

    cell.yes.tag = indexPath.row
    cell.yes.targetForAction("connected", withSender: self)

    println(cell.yes.tag)

    return cell
}


func connected(sender: UIButton!) {

    var query = PFQuery(className:"Contacts")
    query.getObjectInBackgroundWithId(objectIDs[sender.tag]) {
        (gameScore: PFObject!, error: NSError!) -> Void in
        if error != nil {
            NSLog("%@", error)
        } else {
            gameScore["connected"] = "yes"
            gameScore.save()
        }
    }

}

【问题讨论】:

标签: ios swift uitableview parsing


【解决方案1】:

斯威夫特 4 和斯威夫特 5:

您需要为该按钮添加目标。

myButton.addTarget(self, action: #selector(connected(sender:)), for: .touchUpInside)

当然你需要设置那个按钮的标签,因为你正在使用它。

myButton.tag = indexPath.row

你可以通过继承 UITableViewCell 来实现。在界面生成器中使用它,在该单元格上放一个按钮,通过插座连接它,然后就可以了。

在连接函数中获取标签:

@objc func connected(sender: UIButton){
    let buttonTag = sender.tag
}

【讨论】:

  • 如何在连接的函数中获取标签?提前致谢!
  • @André 为您更新了我的答案,可能存在一些语法错误,但这是关于如何获取它的一般想法。
  • 不确定我是否做错了什么,但我相信这在 Swift 2 中不再可能。正如文档中所说:当您调用此方法时,目标不会保留。跨度>
  • @Andrej 而不是使用 'action: "connected:"' 你必须使用 'action: #selector(ClassName.FunctionName(_:)'
  • 如果我有部分,我需要知道部分和行怎么办
【解决方案2】:

使用button.tag 作为实际按下哪个按钮的信息载体的公认答案是可靠的并且被广泛接受但相当有限,因为标签只能包含Ints。

您可以利用 Swift 出色的闭包功能来获得更大的灵活性和更简洁的代码。

我推荐这篇文章:How to properly do buttons in table view cells using Swift closures,作者是 Jure Zove。

适用于您的问题:

  1. 声明一个可以在你的tableview cell中保存一个闭包的变量,比如

    var buttonTappedAction : ((UITableViewCell) -> Void)?
    
  2. 当按钮被按下时添加一个只执行闭包的动作。您使用cell.yes.targetForAction("connected", withSender: self) 以编程方式完成了它,但我更喜欢@IBAction 插座:-)

    @IBAction func buttonTap(sender: AnyObject) {
       tapAction?(self)
    }
    
  3. 现在将func connected(sender: UIButton!) { ... } 的内容作为闭包传递给cell.tapAction = {<closure content here...>}。请参阅文章以获得更准确的解释,并且在从环境中捕获变量时,请不要忘记打破引用循环。

【讨论】:

  • 我认为这种方法比tag 方法要多得多。我一直认为这种方式很挑剔。
  • 这是非常好的方法!谢谢...+1
【解决方案3】:

检测按钮事件并执行某些操作的简单方法

class youCell: UITableViewCell
{
    var yourobj : (() -> Void)? = nil

    //You can pass any kind data also.
   //var user: ((String?) -> Void)? = nil

     override func awakeFromNib()
        {
        super.awakeFromNib()
        }

 @IBAction func btnAction(sender: UIButton)
    {
        if let btnAction = self.yourobj
        {
            btnAction()
          //  user!("pass string")
        }
    }
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
    {
        let cell = youtableview.dequeueReusableCellWithIdentifier(identifier) as? youCell
        cell?.selectionStyle = UITableViewCellSelectionStyle.None

cell!. yourobj =
            {
                //Do whatever you want to do when the button is tapped here
                self.view.addSubview(self.someotherView)
        }

cell.user = { string in
            print(string)
        }

return cell

}

【讨论】:

  • 非常好的解决方案。
  • 谢谢文森特。 :)
  • @R.Mohan 谢谢。
【解决方案4】:
class TableViewCell: UITableViewCell {
   @IBOutlet weak var oneButton: UIButton!
   @IBOutlet weak var twoButton: UIButton!
}


class TableViewController: UITableViewController {

  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TableViewCell

    cell.oneButton.addTarget(self, action: #selector(TableViewController.oneTapped(_:)), for: .touchUpInside)
    cell.twoButton.addTarget(self, action: #selector(TableViewController.twoTapped(_:)), for: .touchUpInside)

    return cell
}

func oneTapped(_ sender: Any?) {

    print("Tapped")
}

func twoTapped(_ sender: Any?) {

    print("Tapped")
   }
}

【讨论】:

    【解决方案5】:

    我们可以为按钮创建一个闭包并在 cellForRowAtIndexPath 中使用它

    class ClosureSleeve {
      let closure: () -> ()
    
      init(attachTo: AnyObject, closure: @escaping () -> ()) {
        self.closure = closure
        objc_setAssociatedObject(attachTo, "[\(arc4random())]", self,.OBJC_ASSOCIATION_RETAIN)
    }
    
    @objc func invoke() {
       closure()
     }
    }
    
    extension UIControl {
    func addAction(for controlEvents: UIControlEvents = .primaryActionTriggered, action: @escaping () -> ()) {
      let sleeve = ClosureSleeve(attachTo: self, closure: action)
     addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
     }
    }
    

    然后在 cellForRowAtIndexPath 中

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
    {
        let cell = youtableview.dequeueReusableCellWithIdentifier(identifier) as? youCell
        cell?.selectionStyle = UITableViewCell.SelectionStyle.none//swift 4 style
    
          button.addAction {
           //Do whatever you want to do when the button is tapped here
            print("button pressed")
          }
    
        return cell
     }
    

    【讨论】:

      【解决方案6】:

      使用 Swift 5,这对我有用!!

      步骤 1. 在 My CustomCell.swift 中为 UIButton 创建 IBOutlet

      class ListProductCell: UITableViewCell {
      @IBOutlet weak var productMapButton: UIButton!
      //todo
      }
      

      Step 2. 在 CellForRowAtIndex 方法中添加 action 方法,并在同一个视图控制器中提供方法实现

      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
              let cell = tableView.dequeueReusableCell(withIdentifier: "ListProductCell") as! ListProductCell
      cell.productMapButton.addTarget(self, action: #selector(ListViewController.onClickedMapButton(_:)), for: .touchUpInside)
      return cell
          }
      
      @objc func onClickedMapButton(_ sender: Any?) {
      
              print("Tapped")
          }
      

      【讨论】:

        【解决方案7】:

        作为Apple DOC

        targetForAction:withSender:
        返回响应的目标对象 一个动作。

        您不能使用该方法为UIButton 设置目标。
        尝试 addTarget(_:action:forControlEvents:)方法

        【讨论】:

          【解决方案8】:

          在 Swift 4 中

          在 cellForRowAt 索引路径中:

           cell.prescriptionButton.addTarget(self, action: Selector("onClicked:"), for: .touchUpInside)
          

          用户按下按钮后运行的函数:

          @objc func onClicked(sender: UIButton){
                  let tag = sender.tag
          
          
              }
          

          【讨论】:

            【解决方案9】:

            公认的答案是好的和简单的方法,但它可以用标签保存的信息有限。有时需要更多信息。

            您可以创建一个自定义按钮并添加任意数量的属性,它们将包含您想要传递的信息:

            class CustomButton: UIButton {
                var orderNo = -1
                var clientCreatedDate = Date(timeIntervalSince1970: 1)
            }
            

            在 Storyboard 中或以编程方式制作这种类型的按钮:

            protocol OrderStatusDelegate: class {
                func orderStatusUpdated(orderNo: Int, createdDate: Date)
            }
            
            class OrdersCell: UITableViewCell {
                @IBOutlet weak var btnBottom: CustomButton!
                weak var delegate: OrderStatusDelegate?
            }
            

            在配置单元格时,将值添加到这些属性中:

             func configureCell(order: OrderRealm, index: Int) {
                 btnBottom.orderNo = Int(order.orderNo)
                 btnBottom.clientCreatedDate = order.clientCreatedDate
             }
            

            点击时访问按钮操作中的那些属性(在单元格的子类中),这些属性可以通过委托发送:

            @IBAction func btnBumpTapped(_ sender: Any) {
                if let button = sender as? CustomButton {
                    let orderNo = button.orderNo
                    let createdDate = button.clientCreatedDate
                    delegate?.orderStatusUpdated(orderNo: orderNo, createdDate: createdDate)
                }
            }
            

            【讨论】:

              【解决方案10】:

              让我提供另一种从其中的按钮获取单元格的方法。

              这个想法是继承 UIButton 只是为了打开一个指向 UITableViewCellweak 指针。

              class MyButton: UIButton {
                  @objc weak var cell: UITableViewCell?
              }
              

              UITableViewCell

              override func awakeFromNib() {
                  super.awakeFromNib()
                  
                  myButton.cell = self
              }
              

              在表格视图的ViewController中,连接按钮的地方:

              @IBAction func myButtonAction(sender: MyButton) {
                  let parentCell = sender.cell
                  ...
              }
              

              【讨论】:

                猜你喜欢
                • 2014-04-19
                • 1970-01-01
                • 1970-01-01
                • 2018-07-16
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-11-07
                相关资源
                最近更新 更多