안녕하세요. 모리스입니다.😀
이번 노트에서는 iOS의 UITableView에서 특정 Section만을 reload하기 위해 reloadSections를 사용하던 중,
앱이 Crash 되는 현상을 겪게 되었고, 그 원인과 해결 과정을 공유해보려 합니다.
❓문제 상황
개발 중이던 UI는 특정 section을 누르면 해당 section이 펼쳐지는 Accordion UI였습니다. 이를 구현하기 위해 다음과 같이 코드를 작성했죠:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch indexPath.section {
case Section.section.rawValue:
self.tableView?.reloadSections(IndexSet(integer: Section.section4.rawValue), with: .automatic)
self.tableView?.reloadSections(IndexSet(integer: Section.section1.rawValue), with: .automatic)
default:
break
}
}
의도한 동작은 특정 셀을 탭하면 1번과 4번 섹션을 reload하여 UI를 갱신하는 것이었어요.
그런데... 셀을 누르는 순간 앱이 Crash😱
🕵️ 원인 분석
Crash 로그를 보며 오랜 시간 삽질을 하다가… 결국 원인은 아주 단순한 것이었습니다.
바로, reloadSections의 순서 문제였습니다.
✅ 1번 섹션을 먼저 reload → 4번 섹션을 나중에 reload
❌ 4번 섹션을 먼저 reload → 1번 섹션을 나중에 reload → Crash
🤔 왜 그럴까?
정확한 내부 동작까지는 알 수 없지만, 추측하건대…
- 1번 섹션은 accordion의 펼침/접힘에 따라 row 개수가 변하는 UI
- 4번 섹션은 화살표 방향 등 상태를 시각적으로 표시하는 UI
이런 상태에서 4번 섹션을 먼저 reload하면, 테이블 뷰는 4번 섹션을 기준으로 레이아웃을 계산하려 하는데, 그 사이에 1번 섹션이 reload되어 전체 레이아웃 구조가 바뀌어버리는 거죠.
즉, 먼저 갱신된 section의 상태에 따라 이후 section의 참조가 꼬이는 문제가 발생하는 것 같습니다.
(정확한 내부 메커니즘을 아신다면 알려주세요🙏)
✅ 해결 방법
순서를 바꾸기만 하면 됩니다. (허무하지만...)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch indexPath.section {
case Section.section1.rawValue:
self.tableView?.reloadSections(IndexSet(integer: Section.section1.rawValue), with: .automatic)
self.tableView?.reloadSections(IndexSet(integer: Section.section4.rawValue), with: .automatic)
default:
break
}
}
결과: 정상 동작! 🎉
🤔 그런데 UI가 어색하다?
accordion이 열리며 reload될 때, UI 애니메이션이 살짝 부자연스럽게 보였습니다.
Apple 문서를 보니 reloadSections 사용 시 다음과 같이 사용하는 걸 권장하더라고요:
self.tableView?.reloadSections(IndexSet(0...4), with: .automatic)
이렇게 하면 0~4번까지 총 5개의 섹션이 한 번에 묶여서 reload되며 UI가 자연스럽게 처리됩니다.
하지만 이 방식은 불필요한 섹션까지 reload되기 때문에 퍼포먼스 이슈가 발생할 수 있습니다.
저는 1번과 4번 섹션만 reload하고 싶었기 때문에 위 방식은 채택하지 않았어요.
더 나은 UX 처리를 위해 custom animation이나 performBatchUpdates 방식도 고민해봐야겠습니다.
'iOS' 카테고리의 다른 글
[iOS] UIImage 초기화 named와 resource (0) | 2025.04.11 |
---|