Cell 재사용시 생기는 문제점 및 해결방법

2021. 7. 6. 11:38iOS

테이블 뷰와 컬렉션 뷰를 설계할 때에는 셀을 재사용(dequeueReusableCell)하는 것을 볼 수 있습니다. 여기서! 왜 셀을 하나하나 만들어주지 않고, 하나의 셀을 만들어 재사용 할까? 라는 궁금증이 생기는데요!!

 

예를 들어 설명해 보겠습니다.

만약 테이블 뷰나 컬렉션 뷰에 표현해야 할 셀이 10개라고 한다면 어떨 것 같나요? 물론 이럴 때에는 굳이 deque하는 방식이 아닌, 데이터소스 개수만큼 cell 객체를 생성해서 테이블 뷰에 보여주면 되지 않나? 라고 생각할 수 있습니다!!

 

하지만 데이터가 10만 개라고 한다면?? 데이터가 10만 개인데, 위와 같은 방식으로 cell을 모두 생성한다면 메모리에 10만 개의 셀을 가지고 있어야 하므로, 메모리 사용량 측면에서 효율이 매우 나쁜 설계가 될 것입니다. 그래서 애플은 dequeueReusableCellWithIdentifier방식으로 테이블 뷰, 컬렉션 뷰를 사용하도록 권장하고 있습니다!!!

 

직접 테이블 뷰를 만들어 시뮬레이터로 실행해보도록 하겠습니다!

위 사진은 셀을 재사용 한 모습인데요! 여기에 문제점이 보이시나요??

저는 맨 위 셀들 중 와이파이, 블루투스, 개인용 핫스팟, 방해금지모드의 switch를 눌러주었지만, 스크롤하여 내려주니 누른 적 없던 항목의 switch가 눌려있는 것을 볼 수 있습니다..!!!

 

이런 현상은 테이블 뷰의 dequeueReusableCell 때문인데요. 

( * 셀의 재사용 구조는 큐로 되어있어 'dequeue'라는 키워드도 등장하는 것입니다. )

 

테이블 뷰에서 화면이 상단으로 스크롤되어 화면에서 사라지는 셀들은 큐로 들어가고, 큐의 front에 있는 셀이 화면의 하단에서 올라와 화면에 보여지는 셀로 사용됩니다. 

 

 

이렇듯 셀에 configure되는 데이터소스의 내용은 다르지만, 셀 자체는 재사용되기 때문에 누른 적 없던 switch가 눌려있는 상태로 보이는 것입니다.

 

잠깐 !

Q. 3번째의 인덱스에게만 스위치를 켜주고 싶다면? 어떻게 하면 될까요??

if indexPath.row == 3 {
	testSwitch.isOn = true
}

위의 코드처럼 해주면 안됩니다!!!!

이렇게 해준다면 3번째의 인덱스 부분이 또 재사용이 되며, 3번째의 인덱스가 재사용 되는 부분에도 스위치가 켜져있을 겁니다!!!

 

💡 해결방법

3번째의 인덱스 부분에만 스위치를 켜주고 싶다면??  

if indexPath.row == 3 {
	cell.testSwitch.isOn = true
}
else {
	cell.testSwitch.isOn = false
}

A. 위의 코드처럼 indexPath.row에 초기 값을 정해줘야 합니다.

이렇게 해주니 원하는 화면이 나오는 것을 볼 수 있습니다!!!

 

정리하자면!!

특정 조건에서 변화를 줬다면, 그 조건에 해당하지 않는 부분도 함께 초기화를 해주어야 한다는 것 !!!! 

 

1) 초기화 prepareForReuse()

하지만 데이터가 가변적이라면??

 

예를들어 지금은 indexPath.row가 3일때만 On이지만, 그것을 Off로 바꾸었다면 어떨까요? 고정된 값이기 때문에 아무리 다른 값으로 바꾸어도 원래 상태로 돌아올 겁니다. 그러므로 고정된 분기처리는 재사용 과정에서 또 다시 문제가 생기게 됩니다.

 

그럴 때마다 값을 하나하나 정해줄 순 없겠죠?? 그래서 사용하는 것이 prepareForReuse() 입니다.

위의 문제는 셀의 속성을 초기화시켜주지 않은 채 재사용해서 발생하는 문제이기 때문에, 재사용되는 셀의 속성을 초기화시켜주면 됩니다!!

// tableViewCell.swift
override func prepareForReuse() {
    super.prepareForReuse()
    
    // 스위치의 초기 상태 지정
    testSwitch.isOn = false

}

아래 그림을 보면 함수가 동작하는 시점을 보다 정확히 알 수 있습니다.  

사진을 보면  prepareForReuse()가 실행된 후 tableView의 cellForRowAt indexPath가 실행되는 것을 볼 수 있습니다.

 

그러니 prepareForReuse()에서 초기값을 설정해 준 뒤, cellForRowAt에서 데이터의 상태를 설정해준다면 가변적인 데이터 또한 재사용 문제를 겪지 않고 제대로 동작하는 것을 알 수 있습니다.   

 

 


참고 ▼

 

[iOS] TableViewCell CollectionViewCell 재사용 문제

TableViewCell이나 CollectionViewCell은 공통점이 있습니다. 그건 바로 셀을 재사용한다는 건데요. 만약 30개의 셀에 각각의 다른 내용을 넣어야한다고 가정했을 때 30개의 셀을 만들어서 관리하면 그만

baechukim.tistory.com

 

[iOS] Cell을 재사용시 생기는 문제점들과 해결 방법

우리는 테이블 뷰와 컬렉션 뷰를 설계할 때 그냥 셀을 사용하지 않고 재활용 셀(dequeueReusableCell)을 사용합니다. 왜 그냥 셀을 사용하지 않고 재활용 셀을 사용하느냐!?  만약에 우리가 테이블 뷰

lsh424.tistory.com

 

iOS) dequeueReusableCellWithIdentifier 과정과 사용이유

테이블뷰, 컬렉션뷰의 셀 재사용에 대해 생각해보자

sihyungyou.github.io

 

'iOS' 카테고리의 다른 글

Storyboard 컴포넌트 알아보기  (0) 2021.06.20
Xcode Project 속성 알아보기  (0) 2021.06.20
AutoLayout이란?  (0) 2021.06.20
Info.plist란?  (0) 2021.06.20
CGPoint와 CGSize, CGRect  (0) 2021.06.02