SwiftUI의 화면 전환은 sheet, popover, NavigationLink, navigationDestination 등 여러 가지 방식이 있지만
오늘은 iOS 16.0 부터 가능한 `NavigationStack`을 `NavigationPath`와 함께 사용해보려고 한다.
앱에서 화면 전환을 할 때, 계속 다음 화면으로 갈 수도 있지만 3개 전 화면으로 이동하거나 초기 화면으로 이동하는 등 화면이 쌓이는 순서를 관리해야할 필요가 있다. 그 방법 중 나는 `NavigationPath`를 선택했다.
이번 글에서는 개념적인 내용은 빼고 사용법만 간단히 작성하려고 한다.
구현하기
먼저 2개의 뷰 화면 `ContentView`, `SecondPage`와 네비게이션 관리를 위한 `NaviManager`를 만들었다.
`NaviManager`에는 path를 선언해준다. `NavigationPath`를 사용하려면 SwiftUI를 import 해줘야 한다.
// NaviManager.swift
import Foundation
import SwiftUI
class NaviManager: ObservableObject {
@Published var path = NavigationPath()
}
뷰 파일이 엄청나게 많아졌을 때 네비게이션 관리를 전역적으로 해야하므로 `NaviManager`는 App 파일에 환경객체로 주입해주었다.
// NavigationTestApp.swift
import SwiftUI
@main
struct NavigationTestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(NaviManager())
}
}
}
이제 사용을 하기만 하면 되는데 우선 전체 코드를 먼저 주고 설명을 해보겠다.
// ContentView.swift
import SwiftUI
struct ContentView: View {
@EnvironmentObject var navManager: NaviManager
var body: some View {
NavigationStack(path: $navManager.path) {
VStack {
Button {
navManager.path.append("\(SecondPage.self)")
} label: {
Text("Go to Second Page")
}
}
.navigationDestination(for: String.self) { value in
if value == "\(SecondPage.self)" {
SecondPage()
}
}
}
}
}
1. `NavigationStack`의 `path`에 `NavigationPath`를 넣어준다.
2. `.navigationDestination(for: )`을 활용해서 들어온 `value` 값에 따라 원하는 화면으로 이동할 수 있도록 한다. `value`의 타입이 꼭 String일 필요는 없고 Int, struct 모두 무관하다.
3. 버튼을 눌렀을 때 `path`에 `value`를 append한다.
정말 이게 전부이다. 만약 화면을 pop하고싶다면 `path.removeLast(_ k: Int = 1)`으로 할 수 있다.
주의할 점
1. `NavigationStack`은 루트뷰에서만 사용해야 한다. (여러 뷰에서 사용하면 안됨) 실제로 나도 이것 때문에 다음 화면이 계속 안떠서 고생했다..
2. `.navigationDestination(for:)`은 `NavigationStack` 내부에 있어야 한다.
3. 만약 `SecondPage`에서 `ThirdPage`로 이동하고자 해도 다음 이동에 대한 선언은 루트뷰에서 해야한다.
.navigationDestination(for: String.self) { value in
if value == "\(SecondPage.self)" {
SecondPage()
} else if value == "\(ThirdPage.self)" {
ThirdPage()
}
}
사실 이전에는 화면 전환 방식도 잘 몰라서 가장 쉬운 방식인 `.navigation(isPresented: )` 방식을 주로 활용했다. 이 방식으로는 현재 화면과 다음 화면 간에만 관리가 가능해서 전체 화면의 스택을 관리하는데는 적합하지 않았다. `NavigationPath`를 도입하고자 할 때마다 오류가 나서 쓰지 못했는데 모두 위 주의할 점을 몰라서 생겼던 오류였다.
'iOS > SwiftUI' 카테고리의 다른 글
[SwiftUI] 버튼 사이즈 유지한 채로 터치 영역만 넓히기 (0) | 2025.05.29 |
---|---|
[SwiftUI] 위도 경도 좌표로 경로선 그리기 (Canvas & Path) (0) | 2024.11.03 |
[SwiftUI] 카카오 로그인 구현하기 (3) | 2024.09.06 |