滚动时添加到 UITableViewCell 的图像出现在错误的行中 [英] Image added to UITableViewCell appears in wrong rows when scrolling

查看:20
本文介绍了滚动时添加到 UITableViewCell 的图像出现在错误的行中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm adding an image to a table view row (actually, I seem to be adding it to the row's cell) when selecting it (and removing when selecting it again). The table view consists of prototype cells.

这有效,但是当我滚动并返回到我之前选择的行时,图像将位于另一行中.此外,该图像也会出现在其他行中.

This works but when I scroll around and get back to the row I had previously selected, the image would be in another row. Also, the image appears in other rows as well.

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

My guess is this happens because the cells are re-used when scrolling. Here's the code of a little sample project:

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

  }

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

I need to have the image stay in the correct row, also when coming back to this view controller. What's the correct way to tackle this? Any advice much appreciated!

编辑:我已经尝试实现马特的答案,但我似乎遗漏了一些东西,因为问题仍然存在.

EDIT: I've tried to implement matt's answer but I seem to be missing something, as the problem is still the same.

EDIT 2:更新,现在按预期工作.

EDIT 2: Updated, working as intended now.

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

}

EDIT 3:正如马特所建议的,这里是上面代码的替代解决方案,它继承了 UITableViewCell 而不是为图像使用标签.

EDIT 3: As matt suggested, here's an alternative solution to the code above which subclasses UITableViewCell instead of using a tag for the image.

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
  }

}

推荐答案

问题是单元格在其他行中重复使用.当它们是时,再次调用 cellForRowAtIndexPath.但如果是,您就不会提供有关该行图像的任何信息.

The problem is that cells are reused in other rows. When they are, cellForRowAtIndexPath is called again. But when it is, you are supplying no information about the image for that row.

解决方案:修复您的模型(即您在 cellForRowAtIndexPath 中查阅的信息),以便它了解图像.在didSelect中,不要直接修改单元格.相反,修改模型并重新加载单元.

The solution: fix your model (i.e. the info you consult in cellForRowAtIndexPath) so that it knows about the image. In didSelect, do not modify the cell directly. Instead, modify the model and reload the cell.

这篇关于滚动时添加到 UITableViewCell 的图像出现在错误的行中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆