iOS에서 작성 화면(UICollectionView 기반) 안에 또 다른 UICollectionView를 두고, 날짜나 이미지처럼 상태를 업데이트해야 하는 경우가 있습니다.
이번 글에서는 실제 구현 중 겪었던 문제를 기반으로, **“날짜 선택 이후 셀이 올바르게 업데이트되지 않는 문제”**를 어떻게 해결했는지를 정리합니다.
특히 핵심 해결책인
👉 “IndexPath 기반 접근을 버리고, 셀 인스턴스를 직접 전달하는 방식”
이 얼마나 강력하고 안전한지 중점적으로 설명합니다.
❗ 문제 상황
아래 구조를 가진 감정일기 작성 화면이 있다고 합시다.
WriteCollectionView (외부)
┗ DiaryWriteDateAndGalleryCell (내부 셀)
┗ internalCollectionView (2개의 섹션)
┣ Date Section → 날짜 셀
┗ Gallery Section → 이미지 셀
사용자가 날짜 셀을 탭하면 DatePicker가 뜨고, 날짜 선택 시 해당 셀만 업데이트되길 원했습니다.
그래서 아래와 같이 구현했습니다.
let targetIndexPath = IndexPath(item: 0, section: 0)
if let cell = writeCollectionView.cellForItem(at: targetIndexPath) as? DiaryWriteDateAndGalleryCell {
cell.updateDate(date)
}
하지만…
날짜는 콘솔에 찍히는데 UI에 반영이 되지 않는 문제가 발생했습니다.
🔍 원인 분석
문제의 핵심은 “IndexPath를 추측해서 셀을 찾았다”는 점입니다.
- 화면 구조가 바뀌면 IndexPath가 달라짐
- 스크롤 또는 레이아웃 변경 중이라 셀을 로드하지 않았을 수도 있음 (cellForItem(at:) → nil)
- 재사용 셀 구조상 configure가 이후에 다시 호출되면서 업데이트를 덮어써버림
즉, IndexPath 기반 접근은 매우 취약합니다.
특히 셀 내부에 또 다른 CollectionView가 있는 경우에는 더더욱.
그 결과:
- cell.updateDate() 가 실제로 실행되지 않거나
- 실행되었더라도 configure()가 다시 호출되어 상태가 덮어써짐
그래서 날짜가 표시되지 않았던 겁니다.
💡 해결 방법: “셀을 직접 전달하자”
핵심 아이디어는 아주 단순합니다.
어떤 셀에서 날짜 선택 UI를 열었는지 그 셀 자신만 알고 있다.
그렇다면 그 셀을 그대로 전달해서 업데이트하면 된다.
즉, IndexPath로 셀을 다시 찾을 필요 자체가 사라진다.
🛠 방법 1: setupDatePicker(attachedTo cell:) 패턴
① DateCell → 부모 셀(DiaryWriteDateAndGalleryCell) → VC로 콜백 전달
이전에는 onTapDate 클로저가 단순히 이벤트만 넘겼다면,
이제는 탭된 셀 자신을 그대로 넘기도록 구조를 바꾼다.
cell.onTapDate = { [weak self, weak cell] in
guard let self, let cell else { return }
self.setupDatePicker(attachedTo: cell)
}
여기서 중요한 것은
weak cell을 캡처하여 정확한 셀 인스턴스를 전달한다는 점입니다.
② setupDatePicker(attachedTo:)에서 셀 직접 업데이트
func setupDatePicker(attachedTo cell: DiaryWriteDateAndGalleryCell) {
let calendarVC = CustomCalendarViewController()
calendarVC.onDateSelected = { [weak self, weak cell] date in
guard let self, let cell else { return }
self.diaryWriteVM.editableDiary.createdAt = date
// 핵심: 전달받은 셀에 직접 업데이트
cell.updateDate(date)
}
present(calendarVC, animated: true)
}
✨ 왜 이 방식이 절대적으로 안전한가?
✔ 1. IndexPath 의존 0%
- 셀의 위치가 바뀌어도
- 화면 구성이 바뀌어도
- 스크롤 상태와 무관하게
셀 인스턴스 자체는 언제나 정확합니다.
✔ 2. 실시간으로 UI 반영
- reloadItems나 reloadData 필요 없음
- 영향을 받는 건 내부 CollectionView의 특정 섹션뿐
- 텍스트, 이미지, 스크롤 위치 모두 유지됨
✔ 3. 재사용 셀 문제에서도 안전
configure가 다시 호출되어도 selectedDate가 직접 관리되기 때문에 상태가 사라지지 않습니다.
DateCell.tap → onTapDate(cell 전달)
↓
DiaryWriteViewController.setupDatePicker(attachedTo:)
↓
날짜 선택 완료 onDateSelected
↓
attached cell.updateDate()
↓
internalCollectionView.reloadSections([.date])
↓
UI 즉시 반영'감정일기(가칭)' 카테고리의 다른 글
| 📘 diariesPublisher vs fetchDiaryByDay (0) | 2025.12.16 |
|---|---|
| 📅 날짜 선택 → 감정일기 리스트 화면 설계하기 (LemonLog 사례) (0) | 2025.12.16 |
| 📘 감정일기 작성 화면에서 날짜 선택 UI는 어떻게 설계해야 할까?— 달력을 직접 넣을까, 시트로 띄울까? 구조적 고민과 결론 정리 (0) | 2025.12.10 |
| 📘 단계형 UI(Form Wizard)에서 유효성 검사를 어떻게 설계할까?— 감정일기 작성 화면(DiaryWrite)을 구현하면서 얻은 설계 인사이트 (0) | 2025.12.09 |
| 📘 DiaryWriteViewController 설계 문서 (함수·프로퍼티 단위 상세 버전) (0) | 2025.12.09 |