iOS - prepareForReuse()

longlivedrgn·2023년 1월 30일
1

iOS

목록 보기
9/10
post-thumbnail

prepareForReuse()

  • tableView를 구현 시, reusableCell을 dequeue할 때 생기는 문제를 해결하는 방법!
  • 먼저, dequeueReusableCell 은 아래의 그림과 같은 과정으로 진행이된다!
  • 이럴 경우, line2에 설정된 attribute이 그대로 line6에 적용이될 수 있다.

이런 문제를 해결하기 위해서는, cell이 reuse되기 전에 prepareForReuse()을 통하여 매번 cell을 초기화해주면 된다.

예제 코드

  • tableview가 존재하고, 해당 tableview는 custom cell인 ReuseCell을 가지고 있다.
  • 해당 tableview는 두 가지의 조건이 있다.
    • row가 0일 경우 cell의 background color를 빨간색으로 설정하고,
    • row가 1일 경우 label2의 text를 “Detail”로 바꾸는 코드이다.
// viewcontroller.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // as ? ! 무엇으로 다운 캐스팅을 해주느냐에 따라서 cell.label?인 지 cell.label인 지 선택할 수 있다.
        let cell = tableView.dequeueReusableCell(withIdentifier: "ReuseCell", for: indexPath) as! ReuseCell
        cell.label.text = "\(indexPath.section), \(indexPath.row)"
        if indexPath.row == 0 {
            cell.backgroundColor = UIColor.systemRed
        }
        if indexPath.row == 1 {
            cell.label2.text = "Detail"
        }
      // indexPath => (Section,Row)
        return cell
    }

// ReuseCell.swift
class ReuseCell: UITableViewCell {

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var label2: UILabel!
}

그런데, 위의 코드는 심각한 오류를 발생시킨다. dequeueReusableCell 과정에서 row가 0인 것 뿐만아니라, row가 1,2인 것도 다 빨간색의 background를 가지게된다.

이는 row가 0이여서 빨간색의 background를 가지게된 cell을 재사용하게되면서 생기는 문제인데, 위의 문제는 아래와 같은 코드로 해결할 수 있다.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // as ? ! 무엇으로 다운 캐스팅을 해주느냐에 따라서 cell.label?인 지 cell.label인 지 선택할 수 있다.
        let cell = tableView.dequeueReusableCell(withIdentifier: "ReuseCell", for: indexPath) as! ReuseCell
        cell.label.text = "\(indexPath.section), \(indexPath.row)"
        if indexPath.row == 0 {
            cell.backgroundColor = UIColor.systemRed
        } else {
            cell.backgroundColor = .none
        }

        if indexPath.row == 1 {
            cell.label2.text = "Detail"
        }
        
//        // indexPath => (Section,Row)
        return cell
    }

그리고, prepareForReuse()를 통해서도 해결이 가능하다.

prepareForReuse() 는 cell이 dequeue되기전에 실행이되며, 셀을 다 초기화해주는 코드가 들어가게 된다.

예제 코드를 통해서 활용을 알아보면, 아래와 같다.

class ReuseCell: UITableViewCell {

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var label2: UILabel!
    
//     이건 처음 로드될 때는 상관 x 다시 reuse될 cell이 생성될 때만!
    override func prepareForReuse() {
        super.prepareForReuse()
        backgroundColor  = .none
        label2.text = nil
    }
}

0개의 댓글