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

Ios 滚动时,添加到UITableViewCell的图像显示在错误的行中,ios,swift,uitableview,Ios,Swift,Uitableview,我在选择一个表视图行时将其添加到表视图行(实际上,我似乎将其添加到该行的单元格中)(再次选择时将其删除)。表格视图由原型单元组成 这是可行的,但当我滚动并返回到我先前选择的行时,图像将位于另一行。此外,图像也显示在其他行中 我猜这是因为滚动时单元格被重复使用。 下面是一个小示例项目的代码: import UIKit class MyTableViewController: UITableViewController { // Using integers for simplicity,

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

这是可行的,但当我滚动并返回到我先前选择的行时,图像将位于另一行。此外,图像也显示在其他行中

我猜这是因为滚动时单元格被重复使用。 下面是一个小示例项目的代码:

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)
    }

  }
导入UIKit
类MyTableViewController:UITableViewController{
//为了简单起见,使用整数也可以处理字符串。
变量编号=[Int]()
重写func viewDidLoad(){
super.viewDidLoad()
对于0..UITableViewCell中的i{
让cell=tableView.dequeueReusableCellWithIdentifier(“TestCell”,forIndexPath:indexPath)
cell.textlab?.text=“\(数字[indexPath.row]+1)”
返回单元
}
重写func tableView(tableView:UITableView,numberofrowsinssection:Int)->Int{
返回数字。计数
}
重写func tableView(tableView:UITableView,didSelectRowAtIndexPath:nsindepath){
让cell=tableView.cellforrowatinexpath(indexPath)!
如果让myImage=curCell.viewWithTag(10)作为?myImage{
myImage.removeFromSuperview()文件
}否则{
让myImage=myImage()
myImage.tag=10
cell.addSubview(myImage)
}
}
我需要让图像保持在正确的行中,当回到这个视图控制器时也是如此。解决这个问题的正确方法是什么? 非常感谢任何建议

编辑:我试图实现matt的答案,但我似乎遗漏了一些东西,因为问题仍然是一样的

编辑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)
    }
  }

}
导入UIKit
类列表项{
变量名称:字符串!
var showsImage=false
init(名称:String){
self.name=名称
}
}
类MyTableViewController:UITableViewController{
变量listItems=[ListItem]()
重写func viewDidLoad(){
super.viewDidLoad()
对于0..UITableViewCell中的i{
让cell=tableView.dequeueReusableCellWithIdentifier(“TestCell”,forIndexPath:indexPath)
cell.textLabel?.text=“\(listItems[indexPath.row].name)”
如果listItems[indexath.row].showsImage{
让myImage=myImage
myImage.tag=10
cell.addSubview(myImage)
}否则{
如果让myImage=cell.viewWithTag(10)作为?myImage{
myImage.removeFromSuperview()文件
listItems[indexath.row].showsImage=false
}
返回单元
}
重写func tableView(tableView:UITableView,numberofrowsinssection:Int)->Int{
返回listItems.count
}
重写func tableView(tableView:UITableView,didSelectRowAtIndexPath:nsindepath){
让cell=tableView.cellforrowatinexpath(indexPath)!
如果让myImage=cell.viewWithTag(10)作为?myImage{
myImage.removeFromSuperview()文件
listItems[indexath.row].showsImage=false
}否则{
listItems[indexath.row].showsImage=true
tableView.reloadRowsAtIndexPaths([indexPath],withRowAnimation:.None)
}
}
}
编辑3:正如matt所建议的,下面是代码的另一种解决方案,上面的代码将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
  }

}
导入UIKit
类MyTableViewCell:UITableViewCell{
var myImage=myImage()
重写初始化(样式:UITableViewCellStyle,reuseIdentifier:String?){
init(样式:style,reuseIdentifier:reuseIdentifier)
myImage.hidden=true
添加子视图(myImage)
}
必需的初始化?(编码器aDecoder:NSCoder){
fatalError(“初始化(编码者:)尚未实现”)
}
}
类列表项{
变量名称:字符串!
var showsImage=false
init(名称:String){
self.name=名称
}
}
类MyTableViewController:UITableViewController{
变量listItems=[ListItem]()
重写func viewDidLoad(){
super.viewDidLoad()
对于0..Int中的i{
返回listItems.count
}
重写func tableView(tableView:UITableView,cellForRowAtIndexPath:nsindepath)->UITableView单元格{
let cell=MyTableViewCell(样式:。默认值,reuseIdentifier:“TestCell”)
cell.textLabel?.text=“\(listItems[indexPath.row].name)”
cell.myImage.hidden=!(列表项[indexath.row].showsImage)
返回单元
}
重写func tableView(tableView:UITableView,didSelectRowAtIndexPath:nsindepath){
将cell=tableView.cellforrowatinexpath(indexPath)设为!MyTableViewCell
listItems[indexPath.row].showsImage=cell.myImage.hidden
cell.myImage.hidden=!cell.myImage.hidden
}
}

问题在于,单元格在其他行中被重用。当它们被重用时,将再次调用
cellForRowAtIndexPath
。但当它被重用时,您没有提供有关该行的图像的信息


解决方案:修复您的模型(即您在
cellforrowatinexpath
中查阅的信息)这样它就能了解图像。在
didSelect
中,不要直接修改单元格。相反,请修改模型并重新加载单元格。

嗨,matt,非常感谢你的帮助。我已经尝试实现你的答案,并将代码示例添加到我的帖子中。我仍然在做一些错误的事情,如果你能快速查看一下,那将是非常好的。Tha谢谢!很好!你就快到了。你只是犯了一个小小的逻辑错误。你的
cellForRow
有这样一个条件:
if listItems[indexath.row].showsImage
,但您忘记了说明否则会发生什么。您需要添加一个删除图像的
else
子句。在这一点上,我认为一切都将开始就绪。换句话说,请记住
cellForRow
必须完全配置每个单元格,因为您永远不知道该单元格是否正确正在重复使用。-另外,请注意,您现在可能会重复向同一单元格添加多个图像视图。T