Deep_Dev
article thumbnail
Published 2024. 4. 4. 22:06
[SwiftUI] NavigationStack 🍎 iOS/SwiftUI

 

✅ 기존의 방식 : NavigationView

기존에는 NaivgationView와 NavigationLink를 통해 타이틀과 뷰를 넣어주는 식으로 사용이 됐다.

var body: some View{
    NavigationView {
    	NavigationLink {
        	뷰(color: .red, order: 1)
       	} label: {
        	Text("타이틀")
        }
    }
}

 

💡 Stack으로 바뀌면서 NavigationView의 어떤 단점을 극복했는지 ? 

NavigationView의 주요 단점 중 하나는 SwiftUI에서 매우 간단한 앱의 경우에도 모든 뷰가 내비게이션 스택에 자동으로 푸시되어 메모리 사용량이 증가할 수 있다는 것이다. 또한, NavigationView를 사용할 때 내비게이션 막대에 대한 사용자 정의 기능을 구현하는 것이 제한적일 수 있다.

 

✅ 새로운 버전 : NavigationStack 구현

 WWDC22때부터 NavigationView가 deprecated가 된 이후, NavigationStack을 사용하게 됐다.

NavigationStack에서는 뷰 대신에 값을 전달한다.

import SwiftUI

struct ContentView: View {
  var body: some View {
    NavigationStack {
      NavigationLink("Go to Child View", value: "10")
        .navigationDestination(for: String.self) { value in
          Text("Child Number is \(value)")
        }
    }
  }
}

NavigationLink에 hashable한 value를 넣어주면 .navigationDestination 메서드로 값을 받아와서 값에 따라 원하는 뷰를 그려줄 수 있다. 

 

즉, NavigationStack은 Stack이 표시하는 모든 데이터를 나타내는 경로를 추적할 수 있다.

이와 관련해서 path 라는 생성자를 사용해서 바인딩하면 뷰의 이동 관리를 더 편하게 할 수 있다.

 

✅ NavigationStack 상태 관리하기

네비게이션으로 들어오고 또 빠져나갈수도 있어야한다.

즉 이전 화면이든 뷰를 타고 타고 왔을때 맨 처음 화면으로든 갈 수 있어야한다는 것이다.

당연히 화면 전환 시 타고 갈때 뷰들이 Stack으로 쌓일것이고 이를 충분히 컨트롤 해줄 수 있다.

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
          Text("Child Number is \(value)")
          
          Button("Go to Root View") {
            stack.removeLast()
          }
        }
    }
  }
}

NavigationStack 선언 시 path를 Binding한 값으로 지정해줄 수 있다.

이를 위해 stack이라는 NavigationPath 타입의 State 변수를 만들어준다.

그러면 해당 stack에 뷰를 타고 타고 갈때마다 path 즉 해당 뷰들이 쌓이는 형태이다.

Go to Root View라는 버튼이 눌리면 UIKit에서 처럼 stack의 마지막 요소 즉 마지막 뷰만 제거해서 바로 이전 상위뷰로 가게된다.

 

✅ NavigationStack의 최상단 뷰로 이동하기

import SwiftUI

struct ContentView: View {
    
    @State var stack = NavigationPath()
    
    var body: some View {
        NavigationStack(path: $stack) {
            NavigationLink("Move to Child View", value: "100")
                .navigationDestination(for: String.self) { value in
                    VStack {
                        NavigationLink("Move to Child's Child View", value: "100")
                        
                        Text("Child Number is \(value)")
                        
                        Button("Move to Parent View") {
                            stack.removeLast() // 이전 부모뷰로 이동
                        }
                        
                        Button("Go to Root View") {
                            reset() // 혹은 stack = .init() 바로 실행
                        }
                    }
                }
        }
    }
    func reset() {
        stack = .init() // stack 초기화 -> 최상위 root 뷰로
    }
}


보시면 계속 무한으로 Child View를 stack에 넣어주면서 들어가게 해주기 위해 NavigationLink를 또 넣어줬다.

이렇게 되면 Go to Child's Child View를 통해 다시 navigationDestination을 돌것이고 동일한 형태의 뷰가 파생되어 들어가질것이다.

여기서 그렇다면 계속 Go to Child's Child View를 클릭하게 되면 stack에 뷰들이 차곡차곡 계속 쌓인다.

이 상황에서 stack.removeLast를 하게 되면 하나만 빠져나오게 된다.

만약 최상단 즉, 루트뷰로 가고 싶다면 해당 path에 들어간 stack을 초기화해주면 되는 것이다.

'🍎 iOS > SwiftUI' 카테고리의 다른 글

[SwiftUI] SwiftData  (0) 2024.04.22
[SwiftUI] TextEditor BackgroundColor 적용  (0) 2024.04.22
[SwiftUI] Property Wrapper ②  (3) 2024.03.27
[SwiftUI] 프로퍼티래퍼 정리  (0) 2024.03.17
[iOS][SwiftUI] @State @Binding  (1) 2024.01.07