为什么UITableView在重新加载数据时会缓存单元格?

时间:2018-08-17 13:37:22

标签: ios swift uitableview

如果您要在具有自定义tableView.reloadData()的表上调用UITableViewCell,那么它将在您重新加载数据时缓存那些单元格。 (此处讨论:https://github.com/nicklockwood/FXForms/issues/92

如果继续重新加载数据,一段时间后,可能会缓存和保留30/40个单元。我的问题是:为什么?

尤其是:

1)重新装入表格后,保留丢失的单元格有什么可能的用途?

2)如何防止/减少存储单元的内存缓存?

3)最重要的是,为什么会这样?为什么在调用reloadData()时保留单元格?

示例

要给您一个基本的代码示例,请单击其中一个单元格,然后,当您看到内存中的对象时,还有更多保留的单元格:

ViewController.Swift

import UIKit

class ViewController: UIViewController {
    let tableViewController = QuizTableViewController(style: .grouped)

override func viewDidLoad() {
    super.viewDidLoad()
    self.setupTableViewController()
}

private func setupTableViewController() {
    self.view.addSubview(tableViewController.view)

    let topAnchor = self.tableViewController.view.topAnchor.constraint(equalTo: self.view.topAnchor)
    let leadingAnchor = self.tableViewController.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor)
    let trailingAnchor = self.tableViewController.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor)
    let bottomAnchor = self.tableViewController.view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)
    NSLayoutConstraint.activate([topAnchor, leadingAnchor, trailingAnchor, bottomAnchor])
}
}

QuizTableViewController.Swift

import UIKit

class QuizTableViewController: UITableViewController {
override init(style: UITableViewStyle) {
    super.init(style: style)
    self.view.translatesAutoresizingMaskIntoConstraints = false
}

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

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 5
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 60
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = QuizCell(subText: "HELLO WORLD")
    cell.textLabel?.text = "THIS IS WHAT IS DISPLAYED"
    return cell
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.reloadData()
}
}

QuizCell.Swift

import UIKit

class QuizCell: UITableViewCell {
weak var subText: UILabel?

init(subText: String) {
    self.subText = UILabel()
    self.subText?.text = subText
    super.init(style: .default, reuseIdentifier: "QuizCell")
}

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

deinit {
    print("This is called after the cache is full.")
}
}

2 个答案:

答案 0 :(得分:0)

问题是您没有使用正确的方法来创建表单元格。您正在QuizCell中显式创建cellForRowAt的新实例。您应该做的是使用dequeueReusableCell使可重复使用的单元格出队。然后您的问题就消失了,因为该表将仅保留所需的最小单元格数。

请找到无数有关使用表视图的教程中的任何示例。

答案 1 :(得分:0)

就像@rmaddy一样,问题在于您如何在cellForRowAt函数中使单元出队。而是将其更改为类似于以下内容的

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "QuizCell", for: indexPath) as! QuizCell
    cell.textLabel?.text = "THIS IS WHAT IS DISPLAYED"
    return cell
}