-
Notifications
You must be signed in to change notification settings - Fork 0
TodoListView 헤더 트러블슈팅 ‐ 네비게이션바 UI
Note
headerView와 연계되는 내비게이션바의 UI를 개선하기 위한 시도를 작성하였습니다.
이 문서를 읽기 전 해당 문서를 먼저 읽고 오는 것을 추천합니다.
해결 PR
사이드 이펙트 해결 PR
2026-03-05.6.21.44.mov |
2026-03-05.6.23.34.mov |
| 개선 전 | 개선 후 |
- 네비게이션 바의 배경색을
.systemBackground로 변경하고, 하단 경계선(shadow)을 제거하고자 함. - iOS 26+에서는 Liquid Glass 등 새로운 디자인이 적용되므로, iOS 17/18에서만 커스텀 적용이 필요.
-
.toolbarBackground(.visible, for: .navigationBar)와.toolbarBackground(Color(.systemBackground), for: .navigationBar)적용. - 배경색은 변경되나, 하단 경계선(shadow)을 숨기는 SwiftUI modifier가 존재하지 않음.
-
onAppear에서UINavigationBarAppearance를 생성하여UINavigationBar.appearance()에 설정. -
shadowColor = .clear로 경계선 제거 성공. - 문제: large → inline 전환 시 SwiftUI가 내부적으로 appearance를 덮어써서 inline 모드에서 적용 안 됨.
- appearance 프록시는 새로 생성되는 navigation bar에만 적용되는 한계.
-
UIViewControllerRepresentable로 실제UINavigationController의 navigation bar 인스턴스에 직접 접근. -
updateUIViewController에서 appearance를 설정하여 large/inline 모두 적용. -
dismantleUIViewController에서configureWithDefaultBackground()로 시스템 기본값 복원. -
#available(iOS 26, *)로 iOS 26 이상에서는 스킵.
-
configureWithOpaqueBackground(): 불투명 배경 (.bar와 유사하지 않음). -
configureWithDefaultBackground(): 시스템 기본 반투명(blur) 배경 (SwiftUI의.bar에 가까움). - UIKit의
UINavigationBarAppearance에서는 SwiftUI의 Material(.bar)을 직접 사용할 수 없음.
-
문제: iOS 18의
onScrollGeometryChange를 사용하여 스크롤을 추적했으나, 이 API는 iOS 17에서 지원되지 않아 KVO 기반의 커스텀 솔루션이 필요함. -
시도 4-1 (superview 체인 탐색):
ScrollViewOffsetTracker(UIViewRepresentable)를.background()로 추가하여 superview 체인을 탐색. 하지만 추가된UIView가UIScrollView외부에 위치하여 탐색에 실패함. - 시도 4-2 (superview + sibling subview 탐색): superview 체인을 올라가며 각 단계에서 sibling subview도 재귀적으로 탐색하도록 로직 변경.
-
결과: iOS 17에서도
UIScrollView인스턴스를 찾아내어 KVO로contentOffset을 연속 추적하는 데 성공함. -
최종 구현: iOS 18 이상은
onScrollGeometryChange를 사용하고, iOS 17은ScrollViewOffsetTracker를 통한 KVO 관찰 방식을 분기하여 사용.
구현 과정에서 iOS 17을 대응하며 몇 가지 부수적인 문제가 발생하여 이를 추가로 해결함.
1. iOS 17 네비게이션 바 투명 현상 (PushNotificationListView)
-
문제: 자체
NavigationStack을 가진 뷰에서 iOS 17 구동 시, 스크롤이 최상단에 위치할 때 네비게이션 바가 투명하게 표시됨 (scrollEdgeAppearance가 nil인 상태가 원인). -
해결:
NavigationBarConfigurator에alwaysVisible: Bool파라미터를 추가함.true일 경우scrollEdgeAppearance에도 기본 배경이 설정되도록 수정함 (iOS 18 이상에서는 발생하지 않으므로 무시됨).
2. 스크롤 트래킹 미작동 이슈
-
문제:
onAppear블록이headerView내부의ScrollView에 위치하여 스크롤 트래커가 제대로 작동하지 않음. -
해결: 트래킹 뷰 위치를
List레벨(.background다음)로 이동하여 스크롤 이벤트를 정상적으로 포착하도록 수정함.
3. headerView 레이아웃 불안정 이슈
-
문제: iOS 17에서
headerView내부에ScrollView(.horizontal)를 배치할 경우 레이아웃이 깨지거나 불안정해지는 현상 발생. -
해결: OS 버전에 따라 분기 처리하여, iOS 17에서는
ScrollView를 제거하고 일반 뷰 형태로 렌더링되도록 수정함.
-
headerView:
safeAreaInset(edge: .top)에 배치하고,VStack으로Divider를 포함함. -
스크롤 추적: 분기된
onScrollOffsetChange로직 적용 (iOS 18+ :onScrollGeometryChange, iOS 17 : KVOScrollViewOffsetTracker). -
headerView 구조 (OS 분기 처리):
- iOS 18+:
ScrollView(.horizontal)+.frame(height: 36)+.scrollDisabled(!isScrollTrackingEnabled)+.contentMargins(.leading, 16)적용. - iOS 17:
ScrollView미사용,headerContent+.padding(.leading, 16)+.frame(maxWidth: .infinity, alignment: .leading)적용.
- iOS 18+:
-
headerView 배경: iOS 26 미만은
Color(.secondarySystemBackground), iOS 26 이상은Color.clear적용. -
Section 상단 separator:
.listSectionSeparator(.hidden, edges: .top)적용 및 첫 번째 row에Divider()overlay 추가 (iOS 26 전용). -
네비게이션 바 커스텀:
NavigationBarConfigurator를 통해 iOS 17/18의 배경색 및 shadow를 조정하고,dismantleUIViewController에서 시스템 복원을 보장함 (자체NavigationStack을 가진 뷰는alwaysVisible: true적용). -
상태 관리:
isScrollTrackingEnabled상태 변수를 통해 초기 레이아웃을 안정화하고,headerView스크롤 활성화 상태를 연동 처리함.
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 적용
푸시 알림 리스트 데이터 최신화 개선하기