[Swift] 셀의 재사용식별자(reuseIdentifier) 관리하기 + Reusable믹스인
⛔️ 셀의 재사용식별자를 관리하는 방법에 대해 개인적으로 공부한 것을 정리한 글입니다. 최대한 올바른 내용만 적기위해 노력하고 있지만 틀린내용이 있을 수 있습니다. 그렇기 때문에 글을 읽으실때 비판적으로 읽어주세요.
틀린내용에 대한 피드백은 메일로 보내주시면 감사하겠습니다🙏🏻
1️⃣ 재사용식별자 기본사용
Swift에서는 UITableView, UICollectionView에서 셀들을 재사용셀큐에서 관리합니다. (화면에 사라진셀을 큐에 넣고 화면에 나타나면 큐에서 셀을 꺼내 재사용) 이렇게 셀을 재사용하기 위해서는
// 식별자와 함께 셀등록
tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
// 재사용셀큐에서 셀꺼내오기위해 식별자사용
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as? CustomCell else { return UITableViewCell() }
/* 코드 생략 */
return cell
}
아쉬운점..
셀타입과 함께 식별자를 같이 등록했는데, 식별자를 이용해서 꺼내올때는 셀타입을 유추하지 못합니다. 그보다도
- 1대1 대응이기 때문에 수정하기가 번거롭다.
- 반복적으로 사용될때도 일리리 찾아서 작성하거나 변경해야된다.
- 오타가날 가능성이 있다. (식별자나 고유키값의 경우 치명적)
- 때에따라 디버깅하기가 힘들다.
- 보안이 필요한 키값의 경우 그대로 노출된다.
2️⃣ 식별자를 static변수로 만들어 주기
다음과 같이 셀자체에서 static한 변수로 식별자를 가지고 있으면 위의 단점들을 어느정도 해결할 수 있습니다.
class CustomCell: UITableViewCell {
static let reuseIdentifier = "CustomCell"
/* 코드생략 */
}
// 셀등록
tableView.register(CustomCell.self, forCellReuseIdentifier: CustomCell.reuseIdentifier)
하지만 매번 셀을 만들때마다 reuseIdentifier변수를 만들어주는 것도 번거롭습니다.
3️⃣ 프로토콜 extension 활용하기
이전에 프로토콜관련 포스트에서도 언급한 방법인데, 프로토콜의 extension을 이용하는 방법입니다.
👉🏻 참고사이트[클릭]
이렇게 프로토콜 extension기능을 활용하면 단순히 셀에 프로토콜을 지정해주는 것만으로 고유식별자를 사용할 수 있게 됩니다.
protocol ReuseIdentifying {
static var reuseIdentifier: String { get }
}
extension ReuseIdentifying {
static var reuseIdentifier: String {
return String(describing: self)
}
}
// 사용
class CustomCell: UITableViewCell, ReuseIdentifying {
/* 코드생략 */
}
tableView.register(CustomCell.self, forCellReuseIdentifier: CustomCell.reuseIdentifier)
String(describing:)..??
String의 생성방법중 하나인 .init(describing:)을 이용했는데 들어온 인자를 그대로 String로 바꿔줍니다. 다음의 애플공식문서를 확인하면 더 이해가 잘 될 것입니다.
👉🏻 링크: init(describing:) - Documentation - Apple Developer)
타입을 얻으려면 Self.self 같은데?
위의 reuseIdentifier메서드에서는 .init(describing:)인자로
class AAA {
func printInstance() {
print("[instance]")
print(self)
print(Self.self)
}
static func printStatic() {
print("[static]")
print(self)
print(Self.self)
}
}
AAA().printInstance()
AAA.printStatic()
[instance]
<xxxxxx.AAA: 0x1258085f0>
AAA
[static]
AAA
AAA
4️⃣ Reusable 믹스인 이용하기
Reusable 깃허브링크 👉🏻 Reusable - Github
믹스인에 관한 블로그글 👉🏻 [김종권의 iOS 앱 개발 알아가기] Mixin 패턴(mix-in), Traits 패턴
아래 코드와 같이 Reusable프로트콜(믹스인)을 지정해주면 됩니다. Reusable을 이용하면 이전에 프로토콜+extension(->이것도 결국 믹스인)으로 구현해준 것과 같이
import UIKit
import Reusable
class CustomCell: UITableViewCell, Reusable {
/* 코드 생략 */
}
// 셀등록
tableView.register(cellType: CustomCell.self)
내부구현을 살펴보면 UICollection+extensin에 기존의 register메서드를 한번 감싸는 형식으로 구현되어 있습니다.
그리고 이전에 기본적인 방법으로 재사용셀큐에서 셀을 꺼내올때
// 재사용셀큐에서 셀꺼내오기위해 식별자사용
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as? CustomCell else { return UITableViewCell() }
/* 코드 생략 */
return cell
}
다음과 같이
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: CustomCell.self)
return cell
}
이 부분도 내부구현을 살펴보면 UICollection+extensin에 기존의 dequeueReusableCell메서드를 한번 감싸는 형식이며, 내부에서