티스토리 뷰
Xcode 13.2 로 iOS 15를 빌드했을 때, 발생하는 문제이다. (iOS 14 이하에서는 발생안함)
# 이슈
cell을 토글하면 isSelected가 잘 토글되고 아래 코드도 잘 동작한다.
class SomeCollectionViewCell: UICollectionViewCell {
override var isSelected: Bool {
willSet {
if newValue {
self.backgroundColor = .red
} else {
self.backgroundColor = .gray
}
}
}
...
}
하지만 사용자의 액션이 아니라 코드로 직접 isSelected 값을 바꾸면
순간적으로는 코드로 세팅해줬던 값으로 바뀌지만, 이전의 isSelected 값으로 다시 원복된다.
디버깅해보면 순차적인 값 변화를 알 수 있지만, 실제 테스트해보면 뷰의 변화가 전혀 안보이기 때문에 isSelected가 일절 안바뀌는 것처럼 보인다.
class SomeCollectionViewCell: UICollectionViewCell {
override var isSelected: Bool {
willSet {
if newValue {
self.backgroundColor = .red
} else {
self.backgroundColor = .gray
}
}
}
...
func configure(number: Int) {
...
self.isSelected = true
}
}
# 원인 분석 (1)
왜 iOS 15에서 동작이 달라졌을까,,, 하면서 찾아보니
WWDC 2021 > Make blazing fast lists and collection views 에서
collectionview cell prefetching이 확장되었다고 했다.
이것이 원인인가 싶어 prefetching 옵션을 끄고 돌려봐도 여전히 똑같았다.
self.collectionView.isPrefetchingEnabled = false
이것은 원인이 아닌 것으로 판단!
# 원인 분석(2)
UICollectionViewCell > isSelected 문서를 보자.
직접 이 value를 설정하지 말라고 되어있다. 코드로 바꾸면 cell appearance가 안바뀔 것이라고 하면서,,
적절하게 cell을 select 또는 higlight 하는 방법은 collection view의 selection methods를 사용하는 것이라고 한다.
혹시 다른 isSelected 도 코드로 값을 바꾸지 말라고 되어있나..? 하고 isSelected 문서들을 읽어봤는데,
UICollectionViewCell > isSelected 에만 그렇게 되어어있음!
https://developer.apple.com/search/?q=isSelected
그럼 문서에 나와있는데로 collection view의 selection methods를 사용해보자.
이번에는 테스트할 때, 구분을 해주기 위해서 전체 selection이 아닌 반만 selection 하도록 해줬다.
configure에서 isSelected 해주는 코드도 지워줬다.
class SomeCollectionViewCell: UICollectionViewCell {
override var isSelected: Bool {
willSet {
if newValue {
self.backgroundColor = .red
} else {
self.backgroundColor = .gray
}
}
}
func configure(number: Int) {
...
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(SomeCollectionViewCell.self, for: indexPath)
cell.configure...
if indexPath.row % 2 == 0 {
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically)
} else {
collectionView.deselectItem(at: indexPath, animated: false)
}
return cell
}
그럼 iOS 15에서는 잘된다.
하지만 iOS 14는 동작안한다. (iOS 13도 마찬가지)
그럼 결국 모든 버전을 대응하기 위해서는 이렇게 해야한다는 것인가!!!!
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(ChapterNumberCollectionViewCell.self, for: indexPath)
cell.configure...
if indexPath.row % 2 == 0 {
cell.isSelected = true
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically)
} else {
cell.isSelected = false
collectionView.deselectItem(at: indexPath, animated: false)
}
return cell
}
# 해결방안
위와 같이 코드를 작성하면 혼란을 줄 수 있고 문서에서 권장하지 않는 방법 (= isSelected를 코드로 바꾸는 것) 을 여전히 사용하는 셈이다.
그래서 코드로 isSelected를 수동으로 바꿔야하는 경우가 있다면, own property 나 method 를 두는 것이 좋다.
예를들어 아래와 같은 메소드를 만들어주고 (UITableviewCell 의 setSelected(_:animated:) 와 비슷한 형태로 만들어줌)
코드로 isSelected를 바꾸지 않도록 해주는 것이다.
그럼 버전 상관없이 잘 동작!
class SomeCollectionViewCell: UICollectionViewCell {
override var isSelected: Bool {
willSet {
self.setSelected(newValue)
}
}
...
func configure(number: Int) {
...
self.setSelected(true)
}
private func setSelected(_ selected: Bool) {
if selected {
self.backgroundColor = .red
} else {
self.backgroundColor = .gray
}
}
}
# 참고 (비슷한 이슈 제보)
https://github.com/Instagram/IGListKit/issues/524
'🍏 > iOS' 카테고리의 다른 글
[iOS] RxSwift 로 살펴보는 써드파티 라이브러리 5가지 사용 방법 (0) | 2022.03.12 |
---|---|
[iOS] Overriding Build Settings for a Target 원복하기 (0) | 2022.02.08 |
[iOS] subview reference strong vs weak (0) | 2021.12.04 |
[Xcode] Xcode 유용한 단축키 모음 (0) | 2021.11.22 |
[iOS] modalPresentationCapturesStatusBarAppearance (0) | 2021.11.09 |
- Total
- Today
- Yesterday
- Flutter 로딩
- Python Type Hint
- Django Firebase Cloud Messaging
- github actions
- SerializerMethodField
- Flutter getter setter
- ribs
- flutter deep link
- Flutter Clipboard
- Watch App for iOS App vs Watch App
- Django Heroku Scheduler
- 플러터 얼럿
- Dart Factory
- Flutter Spacer
- flutter dynamic link
- 구글 Geocoding API
- drf custom error
- 장고 URL querystring
- DRF APIException
- Django FCM
- flutter 앱 출시
- 플러터 싱글톤
- Flutter Text Gradient
- METAL
- ipad multitasking
- PencilKit
- Sketch 누끼
- cocoapod
- 장고 Custom Management Command
- flutter build mode
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |