UICollectionView 를 쓰면서 초기 값이 선택이 되어 있어야 하는 상황에 맞닥뜨렸다.
콜렉션뷰나 테이블뷰나 보통 리스트를 만들고, select 할 것을 찾고 나서 누르는 상황이 나오기 때문에
어떤 cell 이 preSelected 라는게 된다는 건 자주 나올 수 없는 상황이다.
하지만 어떤 경우에는 꼭 필요한 경우가 있을 것이다.
SOPT iOS 과제를 하던 중, Tving 의 컴포넌트를 구현하면서 진행하고 있었다.

MVVM 로 진행하면서 이번에 처음으로 VC 에 직접 뷰를 그려보지 않겠다 라는 마음으로, 세부 View 를 따로 그리고 있었다.
위에 보이는 Header Tap View 를 UICollectionView 로 구현을 하고 있었는데, 첫 cell 이 기본적으로 선택이 되어 있었다.
그래서 UICollectionView 의 delegate 이든 dataSource 든 어떤 메서드가 있겠지 하고서는 평범하게 접근을 했다.
검색을 하고 초기 선택 값을 어떻게 처리해야 하나 찾았다. (초기 선택값이 있는 기능은 처음이었던 것 같기도..?)
https://woongsios.tistory.com/107
cellForItemAt: 에서 select 해주기
cell이 select 되었을 때 셀에 어떤 처리를 해주는 경우가 많이 있죠. cellForItemAt: 에서 원하는 cell을 select 해주려면 어떻게 해야할까요? 접근 먼저 select를 처리해주는 방법부터 알아볼까요? delegate를
woongsios.tistory.com
다음 블로그를 참고하며 음 너무 쉬운뎨? 하면서
Cell 을 그리는 메서드인 "cellForItemAt" 에 코드를 집어넣었다.
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier:
HomeHeaderTabCollectionViewCell.cellIdentifier, for: indexPath) as? HomeHeaderTabCollectionViewCell
else { return UICollectionViewCell() }
if indexPath.item == 0 {
cell.isSelected = true
collectionView.selectItem(at: indexPath,
animated: false, scrollPosition: .init())
}
...
}

multipleSelection 을 쓰는 건 조금 말이 안되기 때문에, .selectItem(...) 을 썼다.
indexPath 가 0번째일 때, cell 은 선택이 되어있다. 라는 심플한 구조였다.
그런데 이제 실제로 돌려보면, 내가 내 상황에 맞지 않게 멍청하게 가장 기본이 되는 원리를 무시하고 썼다. Scroll 이 안되는 CollectionView 에서는 아무 문제가 없었지만,
ISSUE:
Scroll 이 되고 cell 이 reuse 되면서 다시 불러지면,
내가 마지막 indexPath 의 item 을 선택했다 하더라도 0번째 indexPath 의 cell 이 불려지는 순간 나의 의지와는 상관 없게 첫번째 item 이 강제적으로 select 가 되는 문제가 발생했던 것이죠...
[<- 첫 item 이 다시 그려지면 내 강제적으로 선택이 초기화된다. 왜냐면 코드가 그러하니깐... 코드 네버 라이]
그래서 다른 delegate 이나 dataSource 에서 방법이 있을까 하다가,
간단하게 1) UICollectionView 내부에서 조건을 걸고, 2) 외부 변수에 Bool 로 조건을 달아서
처음 그려졌을 때만 선택이 되어 있게 하자. 어차피 다른 item 을 누르고 이동해야지 문제가 생기니깐!
(그냥 첫번째 item 이 선택이 되어 있는 상태로 유지가 되는 상황이면 issue 랄게 없어지잖아?!)
순서가 조금 이상하게 적혔는데, 2) 부터 설명하면
private var isHomeSelected = true
UICollectionViewDelegate 함수들 외부에 다음과 같은 Bool 값을 초기값으로 받아 놓는다.
이 의미는 현재 Home 이라는 탭이 선택이 되어 있는가? 라는 그냥 간단한 조건이다.
1) 그리고 함수 내부(cellForItemAt: )에는 초기 선택될 그 조건이 추가가 되는 것이다.
if indexPath.item == 0 && isHomeSelected == true {
cell.isSelected = true
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .init())
}
isHomeSelected 도 동시에 true 일 때만 첫번째 cell 이 선택이 되어 있을거다.
즉, 뷰가 처음 그려졌을 때는 무조건 선택이 되어 있을 것이다. 라는 얘기이다.
추가적으로, 위에서 말했듯이 다른 item 을 눌러야 Issue 가 발생하는 상황이기 때문에 didSelectItemAt(: ) 함수를 사용해야 했다.
만약, 다른 item 을 누르면 0번째 item 이 다시 그려져도 select 가 되면 안되니깐 말이다.
그래서 우리가 추가한 조건을 false 로 바꾼다. 그러면 위의 조건은 만족하지 않게 된다.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
...
isHomeSelected = false
...
}
이렇게 바꾸고 나니, 선택이 초기화되는 Issue 는 해결됐다. 끝.
사실 별건 아닌데, 뭔가 뚝딱 해결한 것 같아 뚝딱뚝딱 적어 올린다.
TIL 하면서 느낀건 어떻게든 적고 정리하면 이해가 확실히 깊어지는 느낌이라.
SOPT iOS 짱
'⌨️ UIKit' 카테고리의 다른 글
| UISrollView 그냥 이렇게 써보자. [예시 코드 딱!] (0) | 2023.05.18 |
|---|---|
| SwiftLint 를 Xcode에 적용시키기 (이슈 및 헷갈렸던 점도 포함!) (0) | 2023.05.15 |
| [URLSession(1)] Swift를 통해 JSON Encoding Decoding 할 때 받아온 JSON 의 Key 가 SnakeCase 라면 어떻게 할까? + 오류 (Codable, CodingKeys) (2) | 2023.05.08 |
| UICollectionView 를 통해 애니메이션이 있는 Segmented TapView 구현해보기 (0) | 2023.05.02 |
| [UIKit] UIPageViewController 에서 Swipe 기능 빼기 + 버튼으로 넘기기 (0) | 2022.12.29 |
댓글