안녕하세요. 도미닉입니다.
오늘은 iOS 테이블뷰에서 셀의 재사용에 대해서 정리해보겠습니다.
dequeueReusableCell(withIdentifier:for:)
일반적으로 테이블뷰에서 셀을 리턴하는 함수에서 셀을 재사용하도록 습관적으로 아래와 같이 코드를 작성하고 있습니다.
이 dequeueReusableCell(withIdentifier:for:) 메소드는 무엇일까요?
지정된 재사용 식별자(indexPath)에 대해 재사용이 가능한 테이블 뷰 셀 객체를 반환하고 테이블뷰에 추가한다.
라고 공식 문서에 나와있습니다.
파라미터와 리턴되는 값이 대해 정리해보겠습니다.
파라미터
identifier
- 재사용할 셀 객체를 식별하기 위한 문자열입니다. 이 매개 변수는
nil
이 아니어야합니다.
indexPath
- 셀의 위치를 특정하는 식별자입니다. 항상 데이터 원본 객체에서 제공하는 index path를 지정하십시오. 이 메소드는 index path를 사용하여 테이블뷰에서 셀의 위치를 기반으로 추가 구성을 수행합니다.
리턴 타입
UITableViewCell
- 재사용 식별자와 연관된 UITableViewCell 개체입니다. 이 메서드는 항상 유효한 셀을 반환합니다.
dequeueReusableCell(withIdentifier:for:) 메서드는 UITableViewDataSource 역할을 하는 객체의
tableView (_: cellForeRowAt :) 메서드 내에서만 호출이 가능합니다.
이 메서드는 아래 3가지 방법으로 셀을 리턴합니다.
- 기존 셀 타입
- 직접 만든 ITableViewCell 클래스
- 스토리 보드를 사용하여 만든 새로운 셀
데이터 소스의 tableView (_: cellForeRowAt :) 외부에서 셀을 만들어야하는 경우에는 이 메서드 대신에 dequeueReusableCell(withIdentifier :)를 사용할 수 있습니다.
스토리보드에서 셀을 만들은 경우 식별자로 셀을 지정해야합니다.
register (_ : forCellReuseIdentifier :) 또는 register (_ : forCellReuseIdentifier :) 메서드를 사용하여 클래스 또는 nib 파일을 등록 할 수 있으며 dequeueReusableCell(withIdentifier:for:) 메서드를 호출하기 전에 등록해야합니다.
이와 같이 dequeueReusableCell(withIdentifier:for:) 메서드만을 호출하면 셀의 재사용에 문제가 없을까요?
첫번째 row의 셀의 배경색을 바꿔야한다고 칠 때 아래와 같이 코드를 작성할 수 있을 것입니다.
실제로 이렇게 코드를 작성하면 처음에는 잘 동작하지만 테이블뷰를 위아래로 내리면 셀이 큐에 들어갔다가 다른 indexPath.row로 재사용되면서 점점 주황색 셀이 늘어나는 현상을 발견할 수 있습니다.
이럴 때 간단하게 if 문에 else 구문을 추가해서 cell.backgroundColor = .clear 라는 식으로 색상 변경을 원하지 않는 row의 색상을 흰색으로 할 수 있을 것입니다.
하지만 저는 prepareForReuse() 메소드를 활용하는 것을 더 선호합니다.
큐에 들어가서 셀이 다시 처음처럼 비어져서 나오는 방식이 더 맞다고 생각해서 입니다.
prepareForReuse()
공식 문서를 보면 아래와 같이 설명이 나옵니다.
tableview 의 delegate가 셀을 재사용하도록 준비합니다.
UITableViewCell 객체가 재사용 가능한 경우 이 메서드는 UITableView 에 dequeueReusableCell (withIdentifier :) 메서드에서 객체가 반환되기 직전에 호출됩니다.
성능 상의 이유로 콘텐츠와 관련이 없는 셀 속성(예 : alpha, eiditing, 셀 선택 상태)만 reset해야합니다.
tableView (_ : cellForRowAt :)에 있는 테이블 뷰의 델리게이트는 셀을 재사용 할 때 항상 모든 콘텐츠를 reset해야합니다.
셀 객체와 관련된 재사용 식별자가 없으면 이 메서드는 호출되지 않습니다. 이 메서드를 재정의하는 경우 슈퍼 클래스의 같은 메서드를 호출해야 합니다.
설명을 보면 성능 상의 이유로 콘텐츠와 관련이 없는 셀 속성만 reset 해야 한다고 하고 tableView 에 있는 셀은 모든 콘텐츠를 reset해야 한다고 하는데 이 부분은 한번 확인해봐야겠습니다.
저는 커스텀 테이블 뷰 셀 안에 아래와 같이 코드를 작성하여 모든 콘텐츠를 reset 해주고 있습니다.
정리
테이블 뷰를 사용할 때 가장 위에 보여드린 코드와 같이 루틴을 가지고 사용하고 있었습니다.
dequeueReusableCell(withIdentifier:for:) 와 prepareForReuse() 메서드의 공식 문서를 살펴보면서 조금 더 알게 되는 내용도 있었고 머릿 속이 정리되는 느낌이 들었습니다.
대부분의 내용은 아래 참고의 공식 문서 링크를 번역한 것입니다.
조금 번역이 어색한 부분이 있거나 자세히 알고 싶으시면 참고 문서 확인해주시면 좋을 것 같습니다.
글 읽어주셔서 감사합니다.
참고 :