添加到UITableViewCell的图像在滚动时显示在错误的行中

时间:2016-03-08 16:54:49

标签: ios swift uitableview

我在选择图像时将图像添加到表格视图行(实际上,我似乎将其添加到行的单元格中)(并在再次选择时删除)。表视图由原型单元组成。

这样可行但是当我滚动并回到我之前选择的行时,图像将在另一行中。此外,图像也出现在其他行中。

我的猜测是因为滚动时重复使用了单元格。  这是一个小样本项目的代码:

import UIKit

class MyTableViewController: UITableViewController {

  // Using integers for simplicity, should work with strings, too.
  var numbers = [Int]()

  override func viewDidLoad() {
    super.viewDidLoad()

    for i in 0..<50 {
      numbers.append(i)
    }
  }

  override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("TestCell", forIndexPath: indexPath)
    cell.textLabel?.text = "\(numbers[indexPath.row] + 1)"

    return cell
  }

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

  override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.cellForRowAtIndexPath(indexPath)!

    if let myImage = curCell.viewWithTag(10) as? MyImage {
      myImage.removeFromSuperview()
    } else {
      let myImage = myImage()
      myImage.tag = 10
      cell.addSubview(myImage)
    }

  }

我需要让图像保持在正确的行中,同样在返回此视图控制器时也是如此。解决这个问题的正确方法是什么? 任何建议都非常感谢!

编辑:我已尝试实施亚马逊的答案,但我似乎遗漏了一些东西,因为问题仍然存在。

编辑2 :已更新,现已按预期工作。

import UIKit

class ListItem {

  var name: String!
  var showsImage = false

  init(name: String) {
    self.name = name
  }

}


class MyTableViewController: UITableViewController {

  var listItems = [ListItem]()

  override func viewDidLoad() {
    super.viewDidLoad()

    for i in 0..<50 {
      let listItem = ListItem(name: "row \(i)")
      listItems.append(listItem)
    }
  }


  // MARK: - Table view data source

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

    cell.textLabel?.text = "\(listItems[indexPath.row].name)"

    if listItems[indexPath.row].showsImage {
      let myImage = myImage
      myImage.tag = 10
      cell.addSubview(myImage)
    } else {
      if let myImage = cell.viewWithTag(10) as? myImage {
      myImage.removeFromSuperview()
      listItems[indexPath.row].showsImage = false
    }

    return cell
  }

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

  override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.cellForRowAtIndexPath(indexPath)!

    if let myImage = cell.viewWithTag(10) as? myImage {
      myImage.removeFromSuperview()
      listItems[indexPath.row].showsImage = false
    } else {
      listItems[indexPath.row].showsImage = true
      tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
    }
  }

}

编辑3 :正如亚光提示的那样,这里是上面代码的替代解决方案,其中包含UITableViewCell的子类,而不是使用图像的标记。

import UIKit

class MyTableViewCell: UITableViewCell {

  var myImage = MyImage()

  override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    myImage.hidden = true
    addSubview(myImage)
  }

  required init?(coder aDecoder: NSCoder) {
      fatalError("init(coder:) has not been implemented")
  }

}


class ListItem {

  var name: String!
  var showsImage = false

  init(name: String) {
    self.name = name
  }

}

class MyTableViewController: UITableViewController {

  var listItems = [ListItem]()

  override func viewDidLoad() {
    super.viewDidLoad()

    for i in 0..<50 {
      let listItem = ListItem(name: "row \(i)")
      listItems.append(listItem)
    }
  }


  // MARK: - Table view data source

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

  override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = MyTableViewCell(style: .Default, reuseIdentifier: "TestCell")

    cell.textLabel?.text = "\(listItems[indexPath.row].name)"
    cell.myImage.hidden = !(listItems[indexPath.row].showsImage)

    return cell
  }

  override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.cellForRowAtIndexPath(indexPath) as! MyTableViewCell

    listItems[indexPath.row].showsImage = cell.myImage.hidden
    cell.myImage.hidden = !cell.myImage.hidden
  }

}

1 个答案:

答案 0 :(得分:5)

问题是单元格在其他行中被重用。如果是,则再次调用cellForRowAtIndexPath。但是当它出现时,你没有提供有关该行图像的信息。

解决方案:修复模型(即您在cellForRowAtIndexPath中咨询的信息),以便了解图像。在didSelect中,请勿直接修改单元格。而是修改模型并重新加载单元格。