-
Notifications
You must be signed in to change notification settings - Fork 0
TodoListView 헤더 트러블슈팅 ‐ 스크롤 조정
Note
Section의 header 파라미터의 한계를 체감하고 safeAreaInset(edge: .top)을 사용하여 UI를 개선하기 위한 시도를 작성하였습니다
해결 PR
- TodoListView의
todoListContent에서 Sectionheader:로 headerView를 사용 중이었으나, 헤더의 top/leading/trailing 인셋을 세밀하게 제어할 수 없는 한계가 존재. - 이를 해결하기 위해
safeAreaInset(edge: .top)으로 headerView를 분리하고, 스크롤 시 헤더가 연동되어 움직이는 기능을 구현하려 함.
- Section의
header:파라미터에 headerView를 넣고.listRowInsets(EdgeInsets(top: 0, leading: 16, bottom: -8, trailing: 16))를 적용. -
결과: 스크롤 시
navigationBar밑으로headerView가 들어가서 가려지는 현상 발생.
- Section
header:대신 List에.safeAreaInset(edge: .top)으로 headerView를 배치. - 결과: headerView의 padding으로 인셋 제어는 가능해졌으나, 스크롤 연동 기능(오프셋 추적) 구현이 추가로 필요해짐.
- iOS 18의
onScrollGeometryChange(for:of:action:)으로 스크롤 오프셋을 추적하여 headerOffset에 반영. -
결과: 정상 동작하나 iOS 17 미지원 문제 발생. View+ 확장에
onScrollOffsetChange헬퍼를 만들어 내부에서#available(iOS 18, *)분기 처리하여 대응.
- Section의
.background에 GeometryReader를 넣고, named coordinate space에서 minY를 PreferenceKey로 전달. -
결과:
onPreferenceChange가 최초 1회만 호출되고 스크롤 중에는 업데이트되지 않음. List 내부의 PreferenceKey는 스크롤 중 연속 전파가 안 되는 SwiftUI의 한계 확인.
- Section이 아닌 개별 row의
.background에 GeometryReader를 배치. -
Array(zip(todos.indices, todos))로 idx를 확인하고idx == 0일 때만 적용 및.onChange(of: minY)로 State 변수 직접 업데이트. - 결과: 최초 스크롤 시 일부 지점에서 위치 이동이 매끄럽지 않은 글리치 현상이 발생하여 폐기.
iOS 17에서도 스크롤 오프셋을 추적하기 위해 UIViewRepresentable을 활용한 KVO(Key-Value Observing) 방식을 도입했습니다. (초기 시도 및 최종 개선안 통합)
-
1차 시도 (단순 superview 탐색):
ScrollViewOffsetTracker를 구현하여 superview를 탐색해 UIScrollView의contentOffset을 관찰하려 함. 하지만 SwiftUI.background()로 추가된 UIView가 UIScrollView 외부에 배치되어 단순히 superview 체인만으로는 UIScrollView를 찾지 못함 (디버그 로그:superview exists: true,UIScrollView not found). 또한contentOffset변화값이 SwiftUI@State로 제대로 전달되지 않는 이슈가 있었음. -
2차 시도 (superview + sibling subview 재귀 탐색): superview 체인을 올라가면서 각 단계에서 sibling(형제) subview도 재귀적으로 탐색하도록 로직을 변경. (
findScrollView: superview 방향 순회 + 각 superview의 sibling subview에서findScrollViewInSubviews호출) -
최종 결과: iOS 17에서 UIScrollView(List 내부의 UICollectionView)를 정상적으로 찾고, KVO로
contentOffset을 연속 추적하는 데 성공함.
최종 구현체 (View+.swift):
onScrollOffsetChange 헬퍼 메서드 내부에서 버전에 따라 분기 처리:
-
iOS 18+: 기본 제공되는
onScrollGeometryChange사용 -
iOS 17:
ScrollViewOffsetTracker를.background()로 추가하여 superview + sibling 탐색으로 UIScrollView를 찾고 KVO 관찰 적용
-
현상: searchable 상태에서 복귀하면 safeAreaInset 내부의 headerView가 보이지 않음 (
onAppear는 호출되나 화면 렌더링 실패). -
원인: headerView 내부의
ScrollView(.horizontal)의 레이아웃 충돌 문제. -
해결:
ScrollView(.horizontal)에.frame(height: 36)으로 고정 높이를 지정하여 레이아웃을 안정화시켜 해결.
- 현상: 콘솔에 "Multiple scroll views were found. Picking the first one to compare." 경고 출력.
-
해결:
onScrollGeometryChange모디파이어를.safeAreaInset보다 앞에 배치하여 오직 List의 스크롤만 감지하도록 순서 변경.
- 현상: searchable에서 돌아오면 가로형 headerView(ScrollView)가 드래그에 의해 통째로 이동 가능해지는 버그 발생.
-
해결: headerView의 ScrollView에
.scrollDisabled(true/false)를 조건부 적용하여 초기 레이아웃 안정화 후 드래그를 방지함.
- 현상: 뷰가 최초 표시될 때 네비게이션 타이틀(large title)이 위아래로 튀는 현상 발생.
-
해결:
isScrollTrackingEnabledState를 추가하고,onAppear이후 0.3초 딜레이를 주어 스크롤 추적을 지연 활성화하도록 처리. (iOS 26은 해결되지 않음)
TagEditor에서 sheet의 detents 최적화(Deprecated)
PushNotificationView의 푸시 알람 기록 UNDO 과정-V1
PushNotificationView의 푸시 알람 기록 UNDO 과정-V2
PushNotificationView의 푸시 알람 기록 UNDO 과정-V3(최종)
Publishing 상태 변환에 따른 에러 해결하기
iOS 17 이하에서 모달의 isPresented 관리하기
LPMetadataProvider로 웹페이지 썸네일 가져오기
Todo-리마인더-구현-트러블슈팅
iOS 17 .searchable 포커싱 이슈 해결기
TodoListView 헤더 트러블슈팅-스크롤 조정
TodoListView 헤더 트러블슈팅-내비게이션바
Todo Response 트러블슈팅
Fastlane을 통한 배포 자동화 트러블슈팅
PushNotification·WebPage 삭제 리팩토링과 Swift Testing 적용
푸시 알림 리스트 데이터 최신화 개선하기