如何快速修复 UITableCells 重复

Posted

技术标签:

【中文标题】如何快速修复 UITableCells 重复【英文标题】:How to fix UITableCells repeating in swift 【发布时间】:2015-07-01 04:43:10 【问题描述】:

我知道这里已经有一些这样的问题,但我无法让它们中的任何一个起作用。基本上,我有一个 ui 表视图,每个单元格中有一个标签和一个开关。每 14 个单元格,开关就会重复一次。 (开关1的状态会改变开关14、28等...)

这是我的代码:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
    // Configure the cell:

    let cell = tableView.dequeueReusableCellWithIdentifier("CompanyCell", forIndexPath: indexPath) as! CompanyCell

    println(companies.count)
    cell.companyName.text = companies[indexPath.row]

    return cell

31 个公司名称的数组被加载到单元格中:

[Apple Inc, American Express Co, ... , Exxon Mobil Corp, Dow Jones]

标签(公司名称)位于单元格的左侧,开关位于单元格的右侧。

那么我怎样才能让细胞停止相互重复使用呢?

【问题讨论】:

你需要在你的cellForRowAtIndexPath方法中设置开关的状态。 @rmaddy 我建议您添加一个答案,以便可以接受。我相信这是正确的解决方案。 【参考方案1】:

现在您有一个模型来表示这个由 31 个公司名称组成的数组。我个人倾向于使用一组自定义的 Company 对象,这些对象不仅包含名称,还包含该公司的状态(即其开关是打开还是关闭):

class Company 
    let name: String
    var state = false

    init(name: String) 
        self.name = name
    

并且,我们还假设您已将单元格中的 UISwitch 连接到 CompanyCell 类中的 IBOutlet

class CompanyCell : UITableViewCell 
    @IBOutlet weak var companyName: UILabel!
    @IBOutlet weak var companySwitch: UISwitch!

如果您有一个属性 companies,它是这些 Company 对象的数组,那么您可以实现 UITableViewDataSource 方法:

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return companies.count


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

    let company = companies[indexPath.row]
    cell.companyName.text = company.name
    cell.companySwitch.on = company.state

    return cell

您可能还想将单元格中开关的“值更改”操作连接到表格视图控制器中的一个方法,如果开关状态发生更改,该方法将更新模型:

@IBAction func didChangeValueInSwitch(sender: UISwitch) 
    let cell = sender.superview?.superview as! CompanyCell
    let indexPath = tableView.indexPathForCell(cell)
    let company = companies[indexPath!.row]
    company.state = sender.on

【讨论】:

【参考方案2】:

当您使用此行重复使用单元格时

let cell = tableView.dequeueReusableCellWithIdentifier("CompanyCell", forIndexPath: indexPath) as! CompanyCell

屏幕外未使用的单元格将返回给您。这个未使用的单元格将具有其属性 - 您的开关状态和根据其旧值设置的公司名称。

现在,您正在根据您的数据更新要设置的companyName,这是完美的:

cell.companyName.text = companies[indexPath.row]

但是,这里您没有设置开关的状态,它仍然具有旧值。您需要维护开关状态的数据并在cellForRowAtIndexPath 方法中进行相应设置。像这样,switchStateArray 是您的开关状态的数据源:

cell.yourSwitch.on = switchStateArray[indexPath.row]

【讨论】:

【参考方案3】:

如果 UITableCells imageview 重复,使用函数 func prepareForReuse()

 class HomeFavoriteCell: UITableViewCell 

        @IBOutlet weak var imglLocation: UIImageView!

        override func awakeFromNib() 
            super.awakeFromNib()
            // Initialization code
        
        override func prepareForReuse() 
            //set your cell's state to default here

            self.imglLocation.image = nil
        

【讨论】:

这会清除第一个和重复单元格的图像,有什么办法可以避免这种情况【参考方案4】:

这是因为您正在使用

重复使用单元格
tableView.dequeueReusableCellWithIdentifier("CompanyCell", forIndexPath: indexPath) as! CompanyCell 

为避免这种情况,请重置cellForRowAtIndexPath 中的开关

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
// Configure the cell:

  let cell = tableView.dequeueReusableCellWithIdentifier("CompanyCell", forIndexPath: indexPath) as! CompanyCell
  cell.mySwitch.on = false // or Whatever your switch name is (from CompanyCell class)
  cell.companyName.text = companies[indexPath.row]

return cell

或创建新的单元格,如

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
// Configure the cell:

  let cell = CompanyCell()
  cell.companyName.text = companies[indexPath.row]

return cell

【讨论】:

不要仅仅因为你有一个开关就停止使用dequeue。这不是一个好主意。正如 rmaddy 所说,cellForRowAtIndexPath 应该设置开关,就像设置 companyName 一样。 为什么我会被否决,我只是给出了所有的选择 您被否决了,因为不建议您按照原始答案的建议关闭出队逻辑。您现在在此处合并的正确答案是保持出队逻辑,但只需设置开关。我建议完全放弃“创建新单元”的讨论,因为那是个坏主意。此外,仅将开关设置为 false 也是一个坏主意。您确实应该参考指示该开关状态的模型。 你们能帮我解决 cellForRowAtIndexPath 函数吗?抱歉,我只是在学习 swift。【参考方案5】:

在你的单元格中写func prepareForReuse()

class CompanyCell : UITableViewCell 
@IBOutlet weak var companyName: UILabel!
@IBOutlet weak var companySwitch: UISwitch!

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

override func prepareForReuse() 
//set your cell's state to default here
self.companySwitch.isOn = false


【讨论】:

以上是关于如何快速修复 UITableCells 重复的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 没有约束的可滑动 UITableCells

修复重复的领域与快速编辑自定义框钩子在Wordpress

如何快速使用异步函数?完成处理程序[重复]

如何修复在 XCUITest 中等待应用空闲的问题

如何阻止我的 tableView 单元格重复使用其中的按钮?

如何使webstorm同时显示多个窗口