【问题标题】:swift reuse cell custom view issue快速重用单元格自定义视图问题
【发布时间】:2019-12-28 03:15:05
【问题描述】:

我在自定义表格视图单元格中有一个自定义视图(tagListView)。 当我在“cellForRowAt”中调用 addTag 到 cell.tagListView 时,它会为每个单元格添加一个标签。 如何仅为该单元格添加标签?我试图保持计数,所以我只为那些没有标签的标签添加标签。但似乎所有细胞的这个计数都是一样的?我知道这与可重复使用的细胞有关。

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = topicListTableView.dequeueReusableCell(withIdentifier: "TopicListTableCell", for: indexPath)
        if let myCell =  cell as? TopicListTableCell {
             if let model=topicListModel{
                let t=model.topics[(indexPath.row)]
                if let subject=t.subject{
                    let (tags,title)=util().getTag(subject: subject)
                     myCell.subject.text=title
                    if(myCell.tagCount==0){
                        myCell.tagList.addTags(tags)
                        myCell.tagCount+=1
                    }
                }
                myCell.content.text=t.content
                myCell.authorTime.text=t.author
                if let replynum=t.replies{
                    myCell.commentNum.text=String(replynum)
                }
                if let upvoteNum=t.score{
                   myCell.upVote.text=String(upvoteNum)
                }
                if indexPath.row%2==1{
                    myCell.background.backgroundColor=util().lightyellow
                }else{
                    myCell.background.backgroundColor=util().darkeryellow
                }

            }
        }

       return cell

    }

单元格代码:

class TopicListTableCell: UITableViewCell{
    @IBOutlet weak var content: UILabel!
    @IBOutlet weak var upVote: UILabel!
    @IBOutlet weak var commentNum: UILabel!
    @IBOutlet weak var subject: UILabel!
    @IBOutlet weak var authorTime: UILabel!
    @IBOutlet weak var background: UIView!
    @IBOutlet weak var tagList: TagListView!
    var tagCount = 0
}

【问题讨论】:

  • 我的想法——我可能错了?简单地在表格视图中“标记”一个 cell 是错误的方法。一个(但不是唯一的)原因是细胞如何被重用。最终,您的表格视图基于某种数组 - 在您的情况下,可能是 topicListModel。为什么不在数组中附加这个“标签”?它更干净,对其他人有意义,并且几乎是不可变的(如果您正确编码)。然后,您只需将此“标签”传递到正确填充的单元格中。
  • 感谢您的想法。这绝对是一个更好的方法。但是如果我的 topiclistmodel 直接来自解析 json ,我应该创建一个不同的类来保存额外的信息吗?
  • 您的代码中缺少空格使其难以阅读。 cell.text = "text"cell.text="text" 更容易阅读。通过更易于阅读的代码,您可以更轻松地在此处获得帮助。
  • 标签有什么用? (标记单元格有什么作用?)
  • 我可以看到太多的 IF LET 语句,你应该改用 Nil-Coalescing Operator

标签: ios swift uitableview


【解决方案1】:

正如 dfd 已经指出的那样,由于 UITableViews 在 iOS 中的工作方式,您的方法并不正确。 您的 tableView 应该有一个数据源(一些数组或字典),其中包含以您想要的方式呈现单元格所需的所有信息。

所以我会创建一个结构,其中包含填充一个单元格所需的所有信息,然后创建一个由这些结构组成的数组,以用他们需要的信息填充所有单元格。 像这样的:

// In your model:
struct TopicItem {
  let topic: Topic
  let tags: [Tag]
  let title: String
}
var topicItems = [TopicItem]()

// This is function is only a draft, so you get a better idea what i mean
func updateTopicItems() {
  topicItems.removeAll()

  for topic in topics {
    let tags: [Tag]
    let title: String

    if let subject = topic.subject {
      // I would refactor this function, it is called getTag() but it returns tags and title. Kinda confusing
      (tags,title) = util().getTag(subject: subject)
    } else {
      tags = [Tag]()
      title = ""
    }

    topicItems.append(TopicItem(topic: topic, tags: tags, title: title))
  }
} 

我还添加了一些重构和 cmets,希望能帮助您在未来保持代码整洁和可维护 :)

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  // cell can be force unwrapped, it will never be something different than a TopicListTableCell, unless you change your code
  // and even then you want a crash, so you find the error fast (crash will only occur during development)
  let cell = topicListTableView.dequeueReusableCell(withIdentifier: "TopicListTableCell", for: indexPath) as! TopicListTableCell
  guard let model = topicListModel else { return cell } // If there is no model, there is nothing to do
  let topicItem = model.topicItems[(indexPath.row)]
  let t = topicItem.topic

  cell.subject.text = topicItem.title

  // You should replace the addTags() function with a setTags() function, otherwise you will get more and more tags every time you present the cell
  cell.tagList.addTags(topicItem.tags)

  cell.content.text = t.content
  cell.authorTime.text = t.author

  if let replynum = t.replies {
    cell.commentNum.text = String(replynum)
  } else {
    // Because cells are getting reused, you need to always set all fields, otherwise you get cells with content from other cells
    cell.commentNum.text = ""
  }

  if let upvoteNum = t.score {
    cell.upVote.text = String(upvoteNum)
  } else {
    // Again always set all fields
    cell.upVote.text = ""
  }

  if indexPath.row %2 == 1 {
    cell.background.backgroundColor=util().lightyellow
  } else {
    cell.background.backgroundColor=util().darkeryellow
  }

  return cell

}

【讨论】: