【问题标题】:How to fix UITableCells repeating in swift如何快速修复 UITableCells 重复
【发布时间】: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 我建议您添加一个答案,以便可以接受。我相信这是正确的解决方案。

标签: ios swift uitableview user-interface tableview


【解决方案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
      }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-20
        • 2014-03-31
        • 1970-01-01
        相关资源
        最近更新 更多