为啥我的 Tableview 重用了一些单元格?

Posted

技术标签:

【中文标题】为啥我的 Tableview 重用了一些单元格?【英文标题】:Why my Tableview is reusing some cells?为什么我的 Tableview 重用了一些单元格? 【发布时间】:2016-10-01 02:05:49 【问题描述】:

我有一个待办事项列表,我在同一个单元格中有一个标签和一个按钮,当我单击按钮时,更改该单元格的图像按钮,但是当我滚动表格视图时,相同的按钮会出现在其他单元格上, 是不会出现在未按下按钮的单元格中。

这是我的 cellForRowAtIndexPath 代码

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

    let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! TaskTableViewCell


    cell.label.text = "Task Number: \(indexPath.row + 1)"
    cell.btnFavorite.setImage(UIImage(named: "star"), forState: .Normal)
    cell.btnFavorite.setImage(UIImage(named: "star-filled"), forState: .Selected)
    cell.btnFavorite.addTarget(self, action: #selector(ListOfTasksViewController.addRemoveFavoriteList), forControlEvents: .TouchUpInside)


    return cell


func addRemoveFavoriteList(sender : UIButton) 
    sender.selected = !sender.selected


自定义 TableViewCell 类:

 import UIKit

class TaskTableViewCell: UITableViewCell 

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var btnFavorite: FavoriteButton!

    override func awakeFromNib() 
        super.awakeFromNib()

    

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

    

    override func prepareForReuse() 
        super.prepareForReuse()
        label.text = nil
        btnFavorite.selected = false

    


视图控制器:

import UIKit

class ListOfTasksViewController: UIViewController, UITableViewDelegate, UITableViewDataSource 

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() 
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self

    

    func numberOfSectionsInTableView(tableView: UITableView) -> Int 
        return 1
    

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return 20
    

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

        let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! TaskTableViewCell


        cell.label.text = "Task Number: \(indexPath.row + 1)"

        cell.btnFavorite.indexPath = indexPath.row

        cell.btnFavorite.addTarget(self, action: #selector(ListOfTasksViewController.addRemoveFavoriteList), forControlEvents: .TouchUpInside)


        return cell
    

    func addRemoveFavoriteList(sender : FavoriteButton) 

        if sender.selected 
            sender.selected = false


         else 
            sender.selected = true

            let index = NSIndexPath(forRow: sender.indexPath, inSection: 0)
            let cell = tableView.cellForRowAtIndexPath(index) as! TaskTableViewCell


        

    





【问题讨论】:

这不是“问题”。重用是正确和可取的行为。毕竟,当您说tableView.dequeueReusableCellWithIdentifier 时,您就接受了它;你认为你在说什么? 按下单元格上的按钮时需要更新数据源。 【参考方案1】:

表格视图中的单元格被重复使用,因此当您向下滚动时,离开屏幕的单元格将被放置在队列的开头,然后再以不同的 indexPath 回到屏幕上。这可能会导致一些问题,因此您需要在自定义单元格类中覆盖 prepareForReuse 方法。

override func prepareForReuse() 

    super.prepareForReuse()

    label.text = nil
    btnFavorite.selected = false

【讨论】:

我这样做了,但是当我按下按钮并向下滚动时,更改的按钮不会出现在其他单元格中,(直到那里没问题)但是当我再次向上滚动时,按下的按钮不是同一张图,你知道为什么吗? 是的,因为该单元格已从屏幕上消失,因此已准备好重新使用,您需要确保您的数据源反映了通过单元格所做的任何更改。所以当你按下按钮时,你必须更新一个反映你的dataSource数组中对应对象的按钮状态的值。 然后当单元格返回屏幕时,在 cellForRowAtIndexPath 中,您需要根据反映按钮状态的对象的值设置按钮的 selected 属性。 显示你的数据源和模型(如果有) 我刚刚创建了我的特定按钮:FavoriteButton : UIButton var isFavorite : Bool?但我没有编写具体的代码来解决这个问题,你有什么建议我怎样才能实现正确的数据源?【参考方案2】:

您需要在 cellforaRowAtIndexPath 中添加条件。

您需要在 Array 中添加标记来跟踪您的选择。 然后检查 cellforRowAtIndexPath。

例如

button.selected= No

if arrselectedIndexpath containObject:indexPath
button.selected =yes

【讨论】:

以上是关于为啥我的 Tableview 重用了一些单元格?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 tableView 中创建一个重用标识符而不是分配/初始化一个单元格?

重用 tableview 单元格中的元素

Tableview 单元格可重用性,切割标签文本

当它们几乎没有区别时,我应该重用 tableView 单元格吗? [关闭]

重用的 tableView 单元格不调用 layoutSubviews 方法

重用自定义 tableView 单元格时重复显示相同的子视图(Swift 4.1)