본문 바로가기

iOS 관련 공부/SwiftUI

SwiftUI - Navigation

하윙,,

내비게이션.. 

UIKit이 익숙한 사람이라면 내비게이션 하면

Navigationbar 이거 생각이 나겠지요..

 

하지만 스유는 NavigationView를 사용했었는데요 이제는 사용하지 않습니다.

NavigationView는 이제 

NavigationStack 과 NavigationSplitView 이 두 가지로 나뉘어서 사용합니다.

 

 

NavigationStack

단일 패널 내비게이션

주로 iPhone에서 사용

화면 전환 방식

navigation stack을 사용해서 루트보기에 뷰 스택을 표시한다.

NavigationLink 를 사용해서 목록과 상세화면을 연결할 수 있다.

NavigarionLink를 클릭하거나 탭하여 스택 상단에 뷰를 추가하고 뒤로가기 버튼이나 스와이프 제스처와 같은 컨트롤을 하여 뷰를 제거할 수 있다.

스택은 항상 제거되지 않은 가장 최근에 추가 된 뷰를 표시하며 루트보기를 제거할 수 없다.

NavigationStack {
    List(items) { item in
        NavigationLink {
            DetailView(item: item)
        } label: {
            Text(item.title)
        }
    }
    .navigationTitle("Items")
}

List: 목록(사이드바 역할)

NavigationLink: 항목을 누르면 상세 화면(DetailView)로 이동

 

 

NavigationSplitView

다중 패널 내비게이션

iPad, Mac에서 자주 쓰이는 마스터-디테일(또는 3패널) 구조를 쉽게 구현할 수 있도록 설계된 뷰 입니다.

패널 분할 방식

왼쪽(마스터): 목록

오른쪽(디테일): 선택된 항목의 상세 정보

이니셜라이저 init(sidebar:detail:) 사용해서 명시적인 사이드 바 및 세부 콘텐츠가 있는 navigation split view를 만듭니다.

NavigationSplitView {
    /* column 1 */
} detail: {
    /* column 2 */
}

 

init(sidebar:content:detail:)

NavigationSplitView {
    /* column 1 */
} content: {
    /* column 2 */
} detail: {
    /* column 3 */
}

NavigationSplitView 를 이용하면 가시성 및 사용자너비를 지정할 수 있다.

 

 

 

NavigationStack NavigationSplitView
단일 패널 내비게이션 (iOS 스타일) 다중 패널 내비게이션 (iPad/Mac 스타일)
주로 iPhone에서 사용 iPad,Mac 에서 강력함
화면 전환(푸쉬/팝) 방식 패널 분할 방식
마스터-디테일 구조 직접 구현 필요 기본적으로 마스터-디테일 구조 제공

 

 

 

 

 

 

+

 

 

그리고 코드보다가 든 궁금증이 생겨서 찾아본게있는데

 

UIKit 사용할 때 Navigation을 사용하면 푸쉬/팝 방식으로 푸쉬해준 화면을 팝해서 없애주고

모달같은 경우에 디스미스해줬던걸로 기억하는데

스유에서는 NavigationStack에서 화면을 닫을 때(즉, 이전 화면으로 돌아갈 때) dismiss를 해주더라고요?

 

찾아보니

SwiftUI에서는 시트(sheet), 팝오버(popover), 네비게이션 푸시 등 다양한 방식으로 화면을 띄울 수 있는데

이때, 현재 화면을 닫고 싶을 때

@Environment(\.dismiss) 를 사용해서 "나를 닫아줘"라고 시스템에 요청하는 것이 표준방식이라고 한다.

 

NavigationStack 에서 NavigationLink 로 이동한 화면이 네비게이션 스택의 맨 위에 쌓이고(푸쉬)

이 화면에 dismiss() 를 호출하면 스택에서 현재 뷰를 팝(pop)해서 이전 화면으로 돌아간다.

즉, dismiss() 는 NavigationStack 에서 pop 동작을 수행한다.

 

직접 pop 대신 dismiss를 쓰는 이유는

UIKit에서는 navigationController.popViewController(animated:) 처럼 명시적으로 pop을 썼지만,

SwiftUI에서는 뷰 계층이 선언적이라 dismiss() 가 더 일관되고 안전한 방법이라 한당!

 

그래서 시트, 팝오버, 네비게이션 등 어떤 방식으로 띄워졌든 동일하게 닫을 수 있다.