[SwiftUI] NavigationStack - go to rootView (NavigationView 활용)

Boogios·2023년 6월 26일
0

[SwiftUI]

목록 보기
4/7
post-thumbnail

시작하기전에...

일단, NavigationStack을 사용했을 경우, rootView로 한번에 되돌아가는 방법은 찾지 못했다.
하루를 꼬박 삽질을 하고 나서 해결을 했다...
A - B - C - D - A 이렇게 되돌아가는 것을 성공했다! 이 방법을 정리해두려고 한당

SwiftUI 4.0에서 발표된 나름 신개념!
iOS 16.0 이상에서만 적용이 되기 때문에 현업에선 아직 쓰이지 않지만 이번 프로젝트에선 16.0으로 맞춰놨으니 활용을 해보자! 하고 써보기 시작했다
(이때까지만해도 이건 너무 쉽다 너무 좋다 이랬더라지...)

import SwiftUI

struct ContentView: View {
  @State var stack = NavigationPath()
  
  var body: some View {
    NavigationStack(path: $stack) {
      NavigationLink("Go to Child View", value: "10")
        .navigationDestination(for: String.self) { value in
          VStack {
            NavigationLink("Go to Child's Child View", value: "20")
            
            Text("Child Number is \(value)")
            
            Button("Go to Parent View") {
              stack.removeLast()
            }
            
            Button("Go to Root View") {
              stack = .init()
            }
          }
        }
    }
  }
}

이런식으로 NavigationStack으로 뷰를 감싸고 NavigationLink로 이동하고 싶은 뷰로 이동을 할 수 있다. value로 원하는 값들도 넘길 수 있어서 편하다고 한다
상단에 NavigationPath()를 @State 변수로 설정해주고 나중에 stack = .init()으로 초기화를 해주면 root view로 이동할 수 있다.

참고 - https://green1229.tistory.com/256

하지만.. 나의 프로젝트에서는 작동하지 않는다..

내 프로젝트들은 총 4개의 View가 개별적으로 존재하지만 위의 코드는 하나의 파일 내에서 Stack이 쌓여나가고 한번에 초기화 시켜줌으로써 모든 Stack view들이 사라져서 가능하다고 생각한다.

@Environment 함수로 바꿔서 값의 상태변화를 계속 넘겨주며 시도를 해봤지만 NavigationStack을 사용해서 한번에 RootView로 가는 방법을 찾지 못했다...

NavigationStack go to root view, Navigation root view 등 수많은 구글링 자료들을 탐색하던 도중... 드디어!!

구세주 발견!!

우선, NavigationStack을 모두 NavigationView로 바꿔주었다.
그리고 넘어갈 버튼들을 NavigationLink로 설정해주었다.

FirstView 설정

struct FirstView: View {
	@State var path: Bool = false
    
    var body: some View {
          NavigationView {
            NavigationLink(destination: SecondView(path: $path), isActive: $path) {
                Text("두번째 화면으로")
            }
          }
          .navigationViewStyle(StackNavigationViewStyle())
	}
}

이렇게 간단하게 이동할 뷰를 destination에 지정해두고 맨 처음 화면으로 돌아오기 위해 @State 변수로 path 값을 넘겨준다.
isActive: 는 변수를 넘겨줄때 true로 바꿔서 넘겨주는 것이다. 맨 끝 화면에 갔을 때, 다시 false로 바꿔주면 다시 초기화면 rootview로 돌아오게 된다.
이렇게 맨 처음 root view를 설정해두고

SecondView 설정

struct SecondView: View {
	@State var path: Bool // 초기값 설정 X
   
    var body: some View {
          Vstack { // NavigationView가 아님
            NavigationLink(destination: ThirdView(path: $path), isActive: $path) {
                Text("세번째 화면으로")
            }
          }
          .navigationBarTitle("두번째 화면")
          .navigationBarBackButtonHidden(true) // 기본 뒤로가기 버튼 숨기기
          .navigationBarItems(leading: backButton) // 뒤로가기 버튼 (아래에서 자세히 다룰 예정)
	}
}

두번째 화면에서도 path 값을 true로 그대로 세번째 뷰로 값을 넘겨주면서 화면전환한다.
아래는 네비게이션바 설정들이다!

LastView 설정

struct LastView: View {
	@State var path: Bool // 초기값 설정 X
   
    var body: some View {
          Vstack { // NavigationView가 아님
            Button(action: {
                path = false
                print("초기 화면으로 돌아가라!")
            }, label: {
                Text("초기화면으로")
            })
          }
          .navigationBarTitle("마지막 화면")
          .navigationBarBackButtonHidden(true) // 기본 뒤로가기 버튼 숨기기
          .navigationBarItems(leading: backButton) // 뒤로가기 버튼 (아래에서 자세히 다룰 예정)
	}
}

맨처음으로 돌아가야 하는 마지막 뷰를 위와같이 설정한다.
path 값을 false로 바꿔주기만 하면 되기때문에 NavigationLink를 쓰지 않고 Button을 사용해줬다.
클릭하며 path 값이 false로 바뀌면서 맨 앞으로 이동하게 된다.

나의 구세주.. https://fwani.tistory.com/16 - 참고자료

네비게이션 뒤로가기 버튼 커스텀

아까 네비게이션 바 설정들을 해줄때 .navigationBarItems()으로 뒤로가기 버튼을 구현해줬다.
.navigationBarBackButtonHidden(true)로 기본 버튼을 숨기고

struct LastView: View {

	@Environment(\.dismiss) private var dismiss

    var backButton : some View {
        Button(
            action: {
                dismiss()
            }) {
                Image(systemName: "chevron.backward")
                    .aspectRatio(contentMode: .fit)
                    .foregroundColor(Color.black)
            }
    }
}

기본으로 제공하고 있는 뒤로가기 버튼 이미지를 지정해준다.
Navigation에서 뒤로가는 방법은 2가지가 있다.
dismiss()와 presentationMode

presentationMode

@Environment(\.presentationMode) var presentationMode
.
.
.
presentationMode.wrappedValue.dismiss()

위와 같이 선언 후 사용했었다. iOS 13, 14까지!!

dismiss

@Environment(\.dismiss) private var dismiss
.
.
.
dismiss()

iOS15부터 dismiss 환경변수를 선언한 뒤, dismiss() 해주면 된다.

마무리하며...

이 글을 쓰는 목적은 다른사람들은 네비게이션 쓸 때, 나처럼 삽질하지 말도록... 남겨놓는 글입니다... 나 또한 다시한번 찾아보는 수고를 덜기위해 내가 보기 편한대로 정리를 해놓은것이라 알아보기 힘들수도 있지만 그래도 조금이라도 도움이 되면 좋겠습니다!!
네비게이션? 이제 마스터다!!! ㅎㅎㅎㅎㅎ

profile
iOS Developer

0개의 댓글