如何在 Swift 中的 UITableViewCell 上添加带有单击事件的按钮?

Posted

技术标签:

【中文标题】如何在 Swift 中的 UITableViewCell 上添加带有单击事件的按钮?【英文标题】:How to add a button with click event on UITableViewCell in Swift? 【发布时间】:2015-05-07 15:15:08 【问题描述】:

在我的主页中,我为 UITableViewCell 创建了一个 xib 文件。我正在从该 xib 文件加载单元格,并且工作正常。

在单元格内部,我有一些标签和按钮。我的目标是通过单击单元格上的按钮来更改标签。

我的代码喜欢下面

import UIKit


class SepetCell: UITableViewCell

    @IBOutlet var barcode: UILabel!
    @IBOutlet var name: UILabel!
    @IBOutlet var fav: UIButton!
    @IBOutlet var strep: UIStepper!
    @IBOutlet var times: UILabel!



    @IBAction func favoriteClicked(sender: UIButton) 
        println(sender.tag)
        println(times.text)

        SepetViewController().favorite(sender.tag)



    
    override func awakeFromNib() 
        super.awakeFromNib()
        // Initialization code
    

    override func setSelected(selected: Bool, animated: Bool) 
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    

这是我作为 .swift 的代码后面的 xib 文件。

主页中的代码如下:

  import UIKit
import CoreData

class SepetViewController: UIViewController, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate 

  @
  IBOutlet
  var sepetTable: UITableView!
    var barcodes: [CART] = []

  let managedObjectContext = (UIApplication.sharedApplication().delegate as!AppDelegate).managedObjectContext

  override func viewWillAppear(animated: Bool) 
    if let moc = self.managedObjectContext 


      var nib = UINib(nibName: "SepetTableCell", bundle: nil)
      self.sepetTable.registerNib(nib, forCellReuseIdentifier: "productCell")
    
    fetchLog()
    sepetTable.reloadData()
  

  func fetchLog() 

    if let moc = self.managedObjectContext 
      barcodes = CART.getElements(moc);
    
  



  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) - > Int 
    return self.barcodes.count
  

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) - > UITableViewCell 


    let cell = tableView.dequeueReusableCellWithIdentifier("productCell") as ? SepetCell


    if cell == nil 
      println("cell nil")

    



    let product: CART
    product = barcodes[indexPath.row]



    cell!.barcode ? .text = product.barcode
    cell!.name ? .text = product.name
    cell!.fav.tag = indexPath.row

    return cell!
  

  func favorite(tag: Int) 



  

当我单击单元格内的收藏按钮时。例如,我想将时间标签文本更改为任何内容。

当我点击收藏按钮时,事件将转到 SepetCell.swift favoriteClicked(sender: UIButton) 函数。

所以,如果我尝试调用: SepetViewController().favorite(sender.tag)

它会进入内部

func favorite(tag: Int) 

      sepetTable.reloadData()

    

但是当 sepetTable 消失时它为零。我认为这是因为当我调用此 SepetViewController().favorite(sender.tag) 函数时。它首先创建 SepetViewController 类。因此,由于未设置对象,因此它为空。

我怎样才能到达那个 sepetTable 或者解决这个问题的最佳方法是什么。

谢谢。

【问题讨论】:

【参考方案1】:

解决这个问题的流行模式是闭包和委托。 如果你想使用闭包,你可以这样做:

final class MyCell: UITableViewCell 
    var actionBlock: (() -> Void)? = nil

然后

    @IBAction func didTapButton(sender: UIButton) 
        actionBlock?()
    

然后在您的 tableview 委托中:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) - > UITableViewCell 

    let cell = tableView.dequeueReusableCellWithIdentifier("MyCellIdentifier") as? MyCell
    cell?.actionBlock = 
       //Do whatever you want to do when the button is tapped here
    

一种流行的替代方法是使用委托模式:

    protocol MyCellDelegate: class 
        func didTapButtonInCell(_ cell: MyCell)
    

    final class MyCell: UITableViewCell 
        weak var delegate: MyCellDelegate?

然后

    @IBAction func didTapButton(sender: UIButton) 
        delegate?.didTapButtonInCell(self)
    

.. 现在在您的视图控制器中:

然后在您的 tableview 委托中:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) - > UITableViewCell 

    let cell = tableView.dequeueReusableCellWithIdentifier("MyCellIdentifier") as? MyCell
    cell?.delegate = self

并像这样添加对协议的一致性:

extension MyViewController: MyCellDelegate 
    didTapButtonInCell(_ cell: MyCell) 
       //Do whatever you want to do when the button is tapped here
    

希望这会有所帮助!

【讨论】:

非常感谢。它对我有用。如果我想从 SepetCell 发送一些东西到 tableView 我应该怎么做?例如,我有一个脱链器,当我点击它时,我想更改标签的值 好的,我通过一些尝试找到了它:) 我对代码进行了一些更改,例如: var onFavButtonTapped : ((Int) -> Void)? = nil **** if let onButtonTapped = self.onButtonTapped onButtonTapped(3) **** cell!.onButtonTapped = (x: Int) in println(x) 很高兴听到!顺便说一句,如果您发现我的回答有用,请考虑投票 :) 是的,我已经尝试过这样做,但由于我是新用户,系统不允许我这样做。它需要至少 15 点声望。抱歉 :) 当我有 15 个代表时,我会这样做 :) 这可能是我开始用 swift 编写代码以来见过的最漂亮的解决方案之一。谢谢你写它!【参考方案2】:

以上所有模式都很好。 我的两分钱,以防您添加按代码(例如多个不同的单元格等..) 有一个 FAR 简单的解决方案。

由于按钮允许指定“目标”,因此您可以在设置时直接将控制器 AND 操作传递给单元格/按钮。

在控制器中:

let selector = #selector(self.myBtnAction)
setupCellWith(target: self, selector: selector)

...

在带有按钮的自定义单元格中:

final func setupCellWith(target: Any? selector: Selector)
       btn.addTarget(target, 
        action: selector,
       for: .touchUpInside)


【讨论】:

【参考方案3】:

凌晨 2 点回答:你想多了。创建一个自定义的 TableViewCell 类;将原型单元类设置为新的自定义类;然后创建一个 IBAction。

【讨论】:

以上是关于如何在 Swift 中的 UITableViewCell 上添加带有单击事件的按钮?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Swift添加Table View搜索框

UITableVIewCell 错误 Xcode 7 / Swift 2

Swift - 使用 UITableViewController 创建子菜单

swift项目第二天:初始化项目

斯威夫特 - UITableViewCell?不能转换为 UITableViewCell

如何从 Swift 3 中的闭包中返回