【Swift】UITableViewのCellは再利用されるよって話


はじめに

今回は皆さんも使ったことあるであろうUITableViewの話をします。
UITableViewのセルはメモリの関係で再利用されます。それゆえに思った通りの挙動になってくれないことがよくあります。

はじめの10個のセルの背景を赤色に変える処理を書いてみましたが、セルが再利用されているため、セルを追加してスクロールすると白色のセルのはずが赤色になってしまいます。

これの対処法を紹介します。

実装

まずはセルの背景を赤くするところまで書きます。

ViewController
final class ViewController: UIViewController {

    @IBOutlet private weak var tableView: UITableView!
    private var testModels = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()

        setData()
        setupTableView()

    }

    private func setData() {
        (1...20).forEach { i in
            testModels.append("Test \(i)")
        }
    }

    private func setupTableView() {
        tableView.dataSource = self
        tableView.register(CustomTableViewCell.nib,
                           forCellReuseIdentifier: CustomTableViewCell.identifier)
        tableView.tableFooterView = UIView()
    }

    @IBAction private func addButtonDidTapped(_ sender: Any) {
        testModels.append("Added Text")
        tableView.reloadData()
    }

}

extension ViewController: UITableViewDataSource {

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: CustomTableViewCell.identifier,
                                                 for: indexPath) as! CustomTableViewCell
        let text = testModels[indexPath.row]
        cell.configure(text: text)
        if indexPath.row < 10 {
            cell.backgroundColor = .red
        }
        return cell
    }

}
CustomTableViewCell
final class CustomTableViewCell: UITableViewCell {

    static var identifier: String { String(describing: self) }
    static var nib: UINib { UINib(nibName: String(describing: self), bundle: nil) }

    @IBOutlet private weak var label: UILabel!

    func configure(text: String) {
        label.text = text
    }

}

ここまでのコードだと先程のような挙動になってしまいます。

次に、カスタムセルに以下のように記述しましょう。

CustomTableViewCell
    override func prepareForReuse() {
        super.prepareForReuse()

        backgroundColor = .white

    }

prepareForReuseは再利用可能なセルを準備するときに呼ばれます。このタイミングで先程挙動がおかしかった背景色を白にします。セルを追加しても初めの10個のセルのみ背景色が赤になることを確認してみてください。

おわりに

おわりです。