我如何在 UITableViewCell 或 UICollectionViewCell 中为 UIButton 编写一个扩展,它只影响它所在的​​单元格?

Posted

技术标签:

【中文标题】我如何在 UITableViewCell 或 UICollectionViewCell 中为 UIButton 编写一个扩展,它只影响它所在的​​单元格?【英文标题】:How can i write an extension for UIButton in UITableViewCell or UICollectionViewCell that only affects the cell which it is inside? 【发布时间】:2019-05-24 07:59:37 【问题描述】:

如您所知,当我们在可重复使用的单元格中声明一个按钮时,它会在滚动 5 或 6 个单元格后重复 UI。 prepareToReuse() 方法只重置 UI,但是为了保持 UI 上的变化,我们需要声明一个字典,

prepareToReuse() 方法只重置 UI,但是;为了保持 UI 的变化 1) 我们需要声明一个字典数组 2)用我们需要的单元格计数的默认值填充该字典 3)改变与我们的单元格相同索引的元素的值 4)在重用单元格时检查我们是否更改了默认值

import UIKit

//defining a enum to track cell state

enum  CellState 
    case selected
    case unselected

    init() 
        self = .unselected
    


class yourCell: UICollectionViewCell 

 @IBOutlet weak var yourBtn: UIButton!

// creating our func
 var buttonAction: (() -> ())?

 override func awakeFromNib() 
        super.awakeFromNib()
    



@IBAction func sliderAction(_ sender: UISlider) 

    // defining our func where we want to use it
    buttonAction()
 




// inside our viewController
import UIKit

class yourViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource 
    @IBOutlet weak var collectionView: UICollectionView!

    // you data source that you fill the cells
    var yourDataArray: [yourDataSource]()

    // the array that will hold status of our cells
    private var  cellStateArray: [CellState]?


    override func viewDidLoad() 
        super.viewDidLoad()

        //confirming our delegate and dataSource
        collectionView.dataSource = self
        collectionView.delegate = self

       //filling your cellStateArray as many as your cell count
       self.cellStateArray = Array(repeating: .unselected, count: self.yourDataArray!.count )
    


    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        if yourDataArray?.isEmpty == false 
            return yourDataArray!.count
         else 
            print("Caution yourDataArray IS EMPTY")
            return 0
        
    

 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "yourCell", for: indexPath) as! yourCell

// checking your button selected or not while reuse it (while scrolling)

     if  cellStateArray![indexPath.row] == .selected  
            cell.yourBtn.backgroundColor = .red
         else 
            cell.yourBtn.backgroundColor = .blue
       


    cell.buttonAction = 

  //calling button function
       button_Select(_ sender: cell.yourBtn, cellStateArray: cellStateArray, indexPath: IndexPath)

 




// Defining the function what you want to do with your button in each cell

func button_Select(_ sender: UIButton, cellStateArray: [CellState], indexPath: IndexPath ) 
        sender.isSelected = !sender.isSelected
        if sender.isSelected
            sender.backgroundColor = .red

           //setting value when your button selected
            cellStateArray[indexPath.row] = .selected
        
        else
            sender.backgroundColor = .blue

          //setting value when your button unselected
            cellStateArray[indexPath.row] = .unselected
        
     collectionView.reloadData()




如果有人需要使用它,我也提到了我自己的方法,但正如您所见,它的路还很长。我的问题是我们是否可以为 UIButton 定义一个扩展来完成相同的工作,或者是否有更短更好的方法来使用它。跟踪 reusableCells 中的重复按钮,如“按钮、开关、复选框等”。有问题不知道为什么苹果不为它做点什么。如果有人告诉我更好的方法,我会很高兴。谢谢。

【问题讨论】:

为什么不在单元格内添加这个按钮?然后使用委托将动作传递给控制器​​ 问题是单元格是可重复使用的,因此当您进行更改时,它会在 6 或 7 个单元格后重复,但在委托和关闭方式中功能不会受到影响。 【参考方案1】:

检查此代码,我已将您的数据源视为模型而不是字典,您可以轻松制作。

class yourCell: UICollectionViewCell 

    @IBOutlet weak var yourBtn: UIButton!

    // creating our func
    var reloadData: (() -> ())?
    var model = yourDataSource()

    override func awakeFromNib() 
        super.awakeFromNib()
    

    @IBAction func sliderAction(_ sender: UISlider) 

        self.model.isSelected = !self.model.isSelected
        reloadData?()
    

    func setCellData(model:yourDataSource)

        self.model = model

        if  model.isSelected  
            yourBtn.backgroundColor = .red
         else 
            yourBtn.backgroundColor = .blue
        

    



// inside our viewController
import UIKit

class yourViewController: UIViewController 

    @IBOutlet weak var collectionView: UICollectionView!

    // you data source that you fill the cells
    var yourDataArray = [yourDataSource]() // considering this as model and has isSelected property (default false)

    override func viewDidLoad() 
        super.viewDidLoad()

        //confirming our delegate and dataSource
        collectionView.dataSource = self
        collectionView.delegate = self

        //fill your model here or pass data as u want

    


extension yourViewController : UICollectionViewDelegate,    UICollectionViewDataSource

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        if yourDataArray?.isEmpty == false 
            return yourDataArray!.count
         else 
            print("Caution yourDataArray IS EMPTY")
            return 0
        
    

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 

        let model = self.yourDataArray[indexPath.row]
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "yourCell", for: indexPath) as! yourCell

        cell.setCellData(model: model)
        cell.reloadData = 

            //reload full collection view or single item 
            self.collectionView.reloadData()
        

        return cell
    

【讨论】:

感谢您的回答。如果你有一个模型,定义一个变量来建模像 var cellButtonState: Bool = false 更容易控制你的 UI 和你的按钮是否被选中,但是如果你没有模型,你应该使用我提到的方式多于。所以我的问题是可以仅使用扩展来跟踪您的按钮,而不是在模型或字典中定义变量,并且可以在单元格中的所有按钮上执行该扩展 @GökhanSayılgan 是的,我正在谈论它我的变量名称是模型中的 isSelected。我们只需要维护单个变量。

以上是关于我如何在 UITableViewCell 或 UICollectionViewCell 中为 UIButton 编写一个扩展,它只影响它所在的​​单元格?的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCell 背景隐藏 UI 元素

多行 UILabel 在 UITableViewCell 内的较小 iPhone 中截断或剪切字符串

在 UITableViewCell 中添加 UICollectionView 后 UI 突然发生变化

UITableViewCell 上的 UIProgressView

如何在 UITableViewCell 中左对齐或右对齐 UILabel

我如何在 UITableViewCell 或 UICollectionViewCell 中为 UIButton 编写一个扩展,它只影响它所在的​​单元格?