참여중인 회사 프로젝트에선 UIKit과 SwiftUI 프레임워크를 함께 사용하고 있는데, 탭바 등 화면전환은 UIKit을 사용 중이어서 사실 SwiftUI의 Navigation 기능을 제대로 써본 적이 없었다. 대신 틈나는대로 직관로그를 SwiftUI로 리팩토링 하고 있어서 겸사겸사 화면전환 관련 로직을 손 대기 전 사전 공부를 할겸 Navigation을 조금 뜯어보기로 했다.
참고로, 이 글에서 다룰 Navigation은 iOS 16 이상을 기준으로 작성했다.
iOS 16 이전엔 NavigationView를 사용하였으나, iOS 16에선 해당 API가 deprecated가 되었다. 해당글에선 iOS 16 이상을 기준으로 작성했기 때문에 NavigationView에 대한 내용은 다루지 않을 예정이다.
현재 SwiftUI 내에서 네비게이션으로 화면전환을 하는 방식은 아래와 같다.
1. NavigationStack + NavigationLink
2. NavigationStack + NavigationDestination
3. NavigationStack + NavigationLink + NavigationDestination
4. NavigationStack + NavigationPath + NavigationDestination
정의
NavigationStack, NavigationLink, NavigationDestination
NavigationStack
: A view that displays a root view and enables you to present additional views over the root view.
애플 공식문서에 따르면, navigationStack은 rootView 를 시작으로 그 위로 view를 쌓을 수 있게 하는 뷰라고 설명하고 있다. 이름에 들어간 "Stack"처럼, 그냥 말그대로 rootview를 맨 밑에 두고 네비게이션 기반으로 차례로 뷰가 쌓인다.
NavigationLink
: A view that controls a navigation presentation.
네비게이션 링크는 네비게이션 전환을 관리하는 뷰.
NavigationDestination
: Associates a destination view with a presented data type for use within a navigation stack.
네비게이션 데스티네이션은 네비게이션 스택를 사용하기 위해 네비게이션 스택에 제시된 데이터와 매치해주는 역할을 한다.
**여기서 데이터는 전환되는 뷰와 타입이 맞는 데이터를 뜻한다.
NavigationStack과 NavigationLink
NavigationStack은 RootView를 맨 밑에 둔 뷰 스택을 관리하고, NavigationLink는 그 뷰 스택에 뷰를 추가하는 역할을 수행한다. 그렇기 때문에 NavigationStack과 NavigationLink는 세트라고 볼 수 있다.
정리하자면 NavigationStack 안에 NavigationLink를 구현해서,
1. 뷰 스택을 만든다 (NavigationStack)
2. 뷰를 추가한다. (NavigaitonLink)
위의 방식을 통하여 SwiftUI 내에서 네비게이션을 구현한다.
위 개념을 활용하여 아주 basic한 단계의 네비게이션 화면전환 예제 코드를 구현해보았다.
Example #1
활용 api:
- https://developer.apple.com/documentation/swiftui/navigationlink/init(_:destination:)-7d6im
가정:
- rootview는 NaviBaseView 이며, 네비게이션 스택뷰 위에 YellowView와 OrangeView를 각각 쌓아서 네비게이션으로 화면 전환을 구현.
- RootView → ChildView (Push, Pop)
코드:
import SwiftUI
struct NaviBaseView: View {
var body: some View {
NavigationStack {
NavigationLink("YellowView") {
NaviYellowView()
}
NavigationLink("OrangeView") {
NaviOrangeView()
}
}
} // body
} // view
- Navigation으로 뷰 전환할 뷰들을 NavigationLink를 써서 NavigationStack에 추가해주었다.
- RootView는 NaviBaseView이기 때문에, 시뮬 영상에서 확인 할 수 있듯이 해당 뷰를 기준으로 뷰가 쌓여서 전환된다.
- 해당 API 의 NavigationLink(“value“ ) value값은 버튼과 같은 역할을 합니다.
Example #2
활용 api:
https://developer.apple.com/documentation/swiftui/view/navigationdestination(for:destination:)
가정:
- NavigationLink의 value값이 아닌 커스텀 버튼을 눌러서 childView로 화면 전환하도록 구현.
코드:
import SwiftUI
struct NaviBaseView: View {
// 1. 버튼 상태값
@State private var isButtonTapped: Bool = false
var body: some View {
NavigationStack {
// 2. 버튼 추가
Button(action: {
isButtonTapped = true
}, label: {
Text("Button")
.frame(width: 100, height: 48)
.background(.green)
})
// 3. 상태값 바인딩 + 이동할 뷰 추가
.navigationDestination(isPresented: $isButtonTapped) {
NaviYellowView()
}
}
} // body
} // view
- 버튼 상태값을 트리거로 네비게이션 화면전환을 하는 기본 코드
data로 전환하는 게 사실 SwiftUI 화면전환의 꽃(?)이라 data를 기준으로 네비게이션 전환 하는 법은 다음 포스팅에 정리해야겠다.
References
https://zeddios.tistory.com/1376
https://www.celinemoon.com/blog/navigationstack-and-navigationpath/
'🍎 Dev > SwiftUI' 카테고리의 다른 글
[SwiftUI] LifeCycle (1) | 2024.10.14 |
---|---|
[SwiftUI] ObservableObject, ObservedObject, Published (6) | 2024.10.07 |
[SwiftUI] scrollTargetLayout과 ScrollTargetBehavior (0) | 2024.08.16 |
[SwiftUI] Property Wrapper 총정리 (0) | 2024.07.26 |
[SwiftUI] Frame (0) | 2024.07.22 |