Cell을 재사용시 생기는 문제점과 해결방안
보통 테이블 뷰와 컬렉션 뷰를 설계할 때는 그냥 셀을 사용하지 않고, 메모리 관리 측면에서 효율적인 재활용 셀 (dequeueReusableCell)을 사용한다.
하지만 셀을 재활용하다 보니 생기는 문제점이 몇 가지가 있다. 대표적인 문제점이 바로 셀의 UI나 속성들이 중첩되거나 반복되는 경우이다.
해결방안
Cell 코드에
var isTouched: Bool? {
didSet {
if isTouched == true {
heartButton.setImage(UIImage(systemName: "heart.fill"), for: .normal)
heartButton.tintColor = UIColor.red
}
else {
heartButton.setImage(UIImage(systemName: "heart"), for: .normal)
heartButton.tintColor = UIColor.lightGray
}
guard let indexPath = getCurrentIndexPath() else { return }
delegate?.didTapHeartButton(at: indexPath)
}
}
Swift
복사
ViewController 코드에
if favKinders.contains(where: { $0.kinderName == kinder.kinderName }) {
cell.isTouched = true
}
else {
cell.isTouched = false
}
Swift
복사
이렇게 하면 해결이 된다.
전체코드
ListViewController.swift
extension ListViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return kinders.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "KinderCell", for: indexPath) as! ListTableViewCell
let kinder = kinders[indexPath.row]
cell.kinderNameLabel.text = kinder.kinderName
cell.kinderAddressLabel.text = kinder.kinderAddress
let insideAirColor = calculateInsideAir(for: kinder.insideAir)
let disinfectionColor = calculateDisinfection(for: kinder.disinfection)
let illuminanceColor = calculateIlluminance(for: kinder.illuminanceDate)
let dustColor = calculateDust(for: kinder.dustDate)
cell.insideAirImageVIew.backgroundColor = insideAirColor
cell.deinfectionImageView.backgroundColor = disinfectionColor
cell.illuminanceImageView.backgroundColor = illuminanceColor
cell.dustImageView.backgroundColor = dustColor
cell.delegate = self
if favKinders.contains(where: { $0.kinderName == kinder.kinderName }) {
cell.isTouched = true
}
else {
cell.isTouched = false
}
return cell
}
}
Swift
복사
ListTableViewCell
//
// ListTableViewCell.swift
// OurKids
//
// Created by KIM Hyung Jun on 2023/08/14.
//
import UIKit
protocol ListTableViewCellDelegate: AnyObject {
func didTapHeartButton(at indexPath: IndexPath)
}
class ListTableViewCell: UITableViewCell {
@IBOutlet weak var backView: UIView!
@IBOutlet weak var kinderNameLabel: UILabel!
@IBOutlet weak var kinderAddressLabel: UILabel!
@IBOutlet weak var heartButton: UIButton!
@IBOutlet weak var insideAirImageVIew: UIImageView!
@IBOutlet weak var dustImageView: UIImageView!
@IBOutlet weak var deinfectionImageView: UIImageView!
@IBOutlet weak var illuminanceImageView: UIImageView!
weak var delegate: ListTableViewCellDelegate?
var isTouched: Bool? {
didSet {
if isTouched == true {
heartButton.setImage(UIImage(systemName: "heart.fill"), for: .normal)
heartButton.tintColor = UIColor.red
}
else {
heartButton.setImage(UIImage(systemName: "heart"), for: .normal)
heartButton.tintColor = UIColor.lightGray
}
guard let indexPath = getCurrentIndexPath() else { return }
delegate?.didTapHeartButton(at: indexPath)
}
}
override func awakeFromNib() {
super.awakeFromNib()
configureUI()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func configureUI() {
insideAirImageVIew.layer.cornerRadius = 7
insideAirImageVIew.clipsToBounds = true
dustImageView.layer.cornerRadius = 7
dustImageView.clipsToBounds = true
deinfectionImageView.layer.cornerRadius = 7
deinfectionImageView.clipsToBounds = true
illuminanceImageView.layer.cornerRadius = 7
illuminanceImageView.clipsToBounds = true
}
@IBAction func heartButtonTapped(_ sender: UIButton) {
if heartButton.imageView?.image == UIImage(systemName: "heart") {
heartButton.setImage(UIImage(systemName: "heart.fill"), for: .normal)
heartButton.tintColor = UIColor.red
}
else {
heartButton.setImage(UIImage(systemName: "heart"), for: .normal)
heartButton.tintColor = UIColor.lightGray
}
guard let indexPath = getCurrentIndexPath() else { return }
delegate?.didTapHeartButton(at: indexPath)
}
private func getCurrentIndexPath() -> IndexPath? {
guard let superView = self.superview as? UITableView else { return nil }
return superView.indexPath(for: self)
}
}
Swift
복사