2026-06-22 (월)
✅ 학습 완료
- 📄 커스텀 CollectionView/TableView 설계 & 구현 (신규)
- Custom UICollectionViewLayout 서브클래싱 — 4가지 필수 오버라이드(prepare, contentSize, layoutAttributesForElements, layoutAttributesForItem)
- Waterfall(Pinterest) Layout 전체 구현 — 가장 짧은 열에 배치, yOffsets 추적
- Circular Layout 구현 — 원 둘레 배치, 삼각함수
- layoutAttributes 심화 — frame/center/transform/transform3D/zIndex/alpha, copy() 필수
- 고급 스크롤 애니메이션 — Parallax 효과, 3D Flip/Scale/Rotation, shouldInvalidateLayout(forBoundsChange:)
- 레이아웃 전환 — setCollectionViewLayout(animated:), 그리드↔리스트, Interactive Transition
- Compositional Layout 고급 — orthogonalScrollingBehavior(가로 스크롤), 섹션별 다른 레이아웃, 배지/데코레이션, visibleItemsInvalidationHandler
- 커스텀 셀 설계 — 컴포넌트 분리, Variants 패턴, ContentConfiguration(iOS 14+), prepareForReuse 최적화
- 제스처 — Long Press + Drag Reordering(beginInteractiveMovementForItem), Swipe Actions
- 📄 스크롤뷰 문서 Q&A 심화 (7절 추가)
- setNeedsDisplay — draw(_:) 오버라이드할 때만
- heightForRowAt 호출 횟수 — estimated 있으면 보이는 셀만, 없으면 전부
- layout.prepare() — collectionViewLayout이 맞음, attributes 계산+캐싱
- FlowLayout vs Compositional vs 커스텀 — 선택 가이드
- UICollectionView 클래스/프로토콜 정리 — Layout(클래스) vs DelegateFlowLayout(프로토콜)
- ⭐ "높이만 알면 frame 자동" — TableView는 세로 1열 고정이라 x,y,width 자동
- 📓 iOS Deep Dive Q&A (로컬 학습노트 —
~/Desktop/iOS_DEEP_DIVE_QA.md)- UICollectionViewDelegate — 프로토콜 채택 vs UICollectionViewController 상속 차이, shouldSelectItemAt 활용
- didSelectItemAt 호출 과정 — 터치 → IOKit → SpringBoard → Mach Port → Run Loop → Hit Testing → 제스처 인식 → 호출
- Run Loop 이벤트 처리 — didSelectItemAt은 Source0, layoutSubviews는 BeforeWaiting
- UIApplication과 UIWindow — 앱당 1개 vs 여러 개 가능, Window Level (normal/statusBar/alert)
- Hit Testing — 서브뷰 역순 탐색 (z-order 위→아래), point(inside:) 오버라이드로 터치영역 확장
- UICollectionViewCell 상속 — NSObject → UIResponder → UIView → UICollectionReusableView → UICollectionViewCell
- UITapGestureRecognizer — 기본적으로 없음 (직접 추가), UIScrollView/CollectionView만 내부 제스처 보유
- 메모리 구조 — Stack(↓높음→낮음), Heap(↑낮음→높음), Data/BSS/Text 영역
- 터치 이벤트 전달 — SpringBoard가 "이 좌표에 어떤 앱 윈도우?" 판단 → Mach Port로 해당 앱에 전송
- 앱 생명주기 — Not Running → Inactive → Active → Background → Suspended
- UIResponder vs UIGestureRecognizer — 저수준 터치 vs 고수준 제스처, Responder Chain vs 상태머신
💡 핵심
Custom Layout 4가지 필수 오버라이드:
| 메서드 | 역할 |
|---|---|
prepare() | 모든 아이템 attributes 미리 계산·캐싱 |
collectionViewContentSize | 전체 콘텐츠 크기 (스크롤 범위) |
layoutAttributesForElements(in:) | 해당 rect에 보이는 요소 반환 |
layoutAttributesForItem(at:) | 특정 아이템 attributes |
Compositional Layout 가로 스크롤:
section.orthogonalScrollingBehavior = .continuous // .paging / .groupPaging / .groupPagingCentered
📕 오답노트
contentInset=0이면 adjustedContentInset도 0?
- ❌ 아니다.
contentInsetAdjustmentBehavior = .automatic(기본값)이면 safe area가 자동 추가됨 contentInset = .zero여도adjustedContentInset.top = 47(노치),.bottom = 34(홈 인디케이터)- 진짜 0 원하면:
.never로 설정
스크롤 최하단 offset.y 계산에 .top 포함?
- ❌ 포함 안 함.
.top은 최상단 계산에만 관여 - 최상단:
offset.y = -adjustedContentInset.top - 최하단:
offset.y = contentSize.height + adjustedContentInset.bottom - bounds.height .top + .bottom은 "스크롤 가능 범위(거리)"를 구할 때 쓰는 것
inset 바꾸면 bounds/frame/contentSize 변함?
- ❌ 안 변함. inset은 "스크롤 범위"만 바꿈
bounds.height= scrollView 자체 크기 (safe area 무관)contentSize= 콘텐츠 크기 (inset과 별개 프로퍼티)- 스크롤 가능 범위 =
top + contentSize + bottom이지만, 각 프로퍼티 값은 그대로
heightForRowAt이 셀 개수만큼 호출된다?
- estimated 없으면 맞음. 100개 셀 → 100번 호출
- estimated 있으면: 보이는 셀만 호출 (10개 정도), 나머지는 추정값으로 contentSize 계산
- 스크롤하면 새로 보이는 셀에 대해 추가 호출
TableView에서 "높이만 알면 frame 자동" — 왜?
- TableView = 세로 1열 누적으로 배치 규칙이 고정
x = 0(항상),width = bounds.width(항상),y = 이전 셀들 높이 합- 그래서 "높이"만 알면 나머지(x, y, width)는 자동 계산
- CollectionView는 자유 배치라 x, y, width, height 전부 알아야 함 → layoutAttributes 필요
관련 문서
·
스크롤뷰 Q&A 심화
layoutAttributesForElements에서 캐시된 attributes를 직접 수정?
- ❌ 하지 마라. 다음 호출 때 오염된 상태로 시작
- ✅ .copy() 후 수정해서 반환 → 원본 캐시 유지
// ❌ cache[i].transform = ... // 원본 오염 // ✅ let attr = cache[i].copy() as! UICollectionViewLayoutAttributes attr.transform = ... return attr