타겟
준비
- 화면 전환 기능을 담당하게 될 Coordinator 함수를 Protocol로 작성합니다 (Coordinator.swift)
- 전환할 모든 화면을 enum 타입으로 작성합니다 (Destination.swift)
- 전환할 View를 만듭니다
CoordinatorProtocol.swift
protocol CoordinatorProtocol {
associatedtype T: Hashable
func push(_ path: T)
func pop()
func popToView(_ to: T)
func popToRoot()
}
Coordinator.swift
final class Coordinator<T: Hashable>: ObservableObject {
@Published var paths: [T] = []
}
extension Coordinator: CoordinatorProtocol {
//다음 화면으로 이동
func push(_ path: T) {
print("PATH: ", paths)
print("추가할 PATH: ", path)
paths.append(path)
print("Result PATH: ", paths)
}
//이전 화면으로 이동
func pop() {
print("PATH: ", paths)
paths.removeLast()
print("Result PATH: ", paths.count)
}
//이전 화면중 특정 화면으로 이동
func popToView(_ to: T) {
print("PATH: ", paths)
guard let found = paths.firstIndex(where: { $0 == to }) else {
return
}
let numToPop = (found..<paths.endIndex).count - 1
paths.removeLast(numToPop)
print("Result PATH: ", paths)
}
//루트뷰로 이동
func popToRoot() {
print("PATH: ", paths)
paths.removeAll()
print("Result PATH: ", paths)
}
}
Destination.swift
// push로 화면전환할 case
enum Destination: Hashable {
case view2
case view3
case view4
case view5
}
RootView.swift
import SwiftUI
struct RootView: View {
@ObservedObject private var coordinator = Coordinator<Destination>()
var body: some View {
NavigationStack(path: $coordinator.paths) {
VStack {
Text("Root View")
Button {
coordinator.push(.view2)
} label: {
Text("Go to second view")
}
.buttonStyle(.borderedProminent)
}
.navigationDestination(for: Destination.self) { destination in
switch destination { // 화면 전환할 모든 화면
case .view2:
ViewTwo()
case .view3:
ViewThree()
case .view4:
ViewFour()
case .view5:
ViewFive()
}
}
}
.environmentObject(coordinator) // coordinator 환경변수 전달
}
}
ViewTwo.swift … ViewFour.swift
import SwiftUI
struct ViewTwo: View {
@EnvironmentObject private var coordinator: Coordinator<Destination>
var body: some View {
VStack {
Text("View Two")
Button {
coordinator.push(.view3)
} label: {
Text("Go to third view")
}
.buttonStyle(.borderedProminent)
}
}
}
ViewFive.swift (LastView)
import SwiftUI
struct ViewFive: View {
@EnvironmentObject private var coordinator: Coordinator<Destination>
var body: some View {
ZStack {
Color.white.ignoresSafeArea()
VStack {
Text("Last View")
Button {
coordinator.popToRoot() // 루트뷰로 이동
} label: {
Text("Root View로 이동")
}
.buttonStyle(.borderedProminent)
}
}
}
}