궁금한 내용을 검색해보세요!
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
서근 개발노트
티스토리에 팔로잉
SWIFTUI/View layout

SwiftUI : NavigationView / NavigationLink

서근
QUOTE THE DAY

“ 공포로 인해 타협하지 말 것이며, 남이 나에게 타협하는 것을 두려워하지도 말라. ”

- Kennedy (케네디)
Written by SeogunSEOGUN

SwiftUI : NavigationView / NavigationLink

 

 

NavigationView 는 SwiftUI의 가장 중요한 구성 요소 중 하나입니다. 화면을 쉽게 PushPop할 수 있으며, 사용자에게 명확하고 계층적인 방식으로 정보를 제공할 수 있습니다

NavigationView를 사용하려면 다음과 같이 항목을 감싸야합니다.

swift
UNFOLDED
struct ContentView: View {
var body: some View {
NavigationView {
Text("Hello, World!")
}
}
}

NavigationView는 최상위에 위치해야 하지만, TabView내에서 사용하는 경우에는 NavigationViewTabView 내에 있어야 합니다.

swift
UNFOLDED
// 옳은 방법
NavigationView {
Text("Hello, World!")
.navigationBarTitle("Navigation")
}
//잘못된 방법
NavigationView {
Text("Hello, World!")
}
.navigationBarTitle("Navigation")

TIP
 
 

NavigationView내에서 navigationBarTitle()를 사용할 수 있으며, 뷰 바깥쪽에서 사용하지 않아도 됩니다. 또한  displayMode parameter 를 사용하여 커스터마징을 할 수 있습니다. 

displayMode

.large 옵션은 내비게이션 스택의 최상위 보기에 유용한 큰 제목을 표시합니다.

.inline 옵션은 내비게이션 스택의 2 차, 3 차 또는 후속 보기에 유용한 작은 제목을 표시합니다.

.automatic 옵션은 기본값이며 이전에 사용한 View를 사용합니다.

swift
UNFOLDED
.navigationBarTitle("Navigation")  //기본값에 .automatic 가 포함 되어 있다.
swift
UNFOLDED
.navigationBarTitle("Navigation", displayMode: .inline)
swift
UNFOLDED
NavigationLink(destination: Text("String"))

SwiftUINavigationViewView의 맨 위에 NavigationBar를 표시하지만 다른 작업도 수행합니다.

 

Viewview stack에 푸시할 수 있습니다. 이것은 iOS view의 가장 기본적인 형태입니다. 예를 들어 WIFI를 탭 하면 설정으로 들어가져서 WIFI 목록을 볼 수 있거나, 연락처에서 이름을 탭 하면 메시지를 보내는 것과 같습니다.

 

TextViewNavigationView래핑하고 제목을 지정하면 다음과 같은 결과가 나타납니다.

swift
UNFOLDED
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
Text("Hello World")
}
.navigationBarTitle("SwiftUI")
}
}
}

→ 기본적인 NavigationView 형태.

 

화면을 보면 텍스트의 Hello Wolrd 에 아무런 변화가 없이 단지 텍스트로 보이죠? 이제 헬로월드를 클릭하면 새로운 탭으로 이동하는 코드를 작성해 봅시다!

swift
UNFOLDED
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: Text("Detail View")) {
Text("Hello World")
}
}
.navigationBarTitle("SwiftUI")
}
}
}

→ 이제 화면에 Hello World부분을 탭할 수 있게 바뀌고 그것을 누르면 Detail View 로 이동할 수 있습니다. 하지만 여기서 의문점이 있습니다.

 

Sheet()NavigationLink차이점이 무엇일까?

 

NavigationLinktopic을 더 자세히 살펴보는 것처럼 사용자가 선택한 것에 대한 세부 정보를 보여 줍니다.

sheet()는 설정 또는 작성 창과 같은 관련 없는 내용을 표시하는 데 사용됩니다.

List에서 row in 하여 Navigationdestination: Textrow를 추가해주고, Text에 도 row를 할당해줍니다.

swift
UNFOLDED
NavigationView {
List(0..<100) { row in
NavigationLink(destination: Text("Detail \(row)")) {
Text("Row \(row)")
}
}
.navigationBarTitle("SwiftUI")
}

SwiftUI : NavigationView / NavigationLink - NavigationLink - List 와 NavigationLink

View를 추가하여 NavigationLink에 연동

만약 동전의 앞과 뒤 중에 골라야 하는 버튼이 있고, 그 버튼을 누르면 "    를 선택하셨습니다" 와 같은 텍스트를 보여주고 싶으면

아래와 같이 ContentView 바깥에 또 다른 View를 생성해 주면 됩니다.

swift
UNFOLDED
struct ResultView: View {
var choice: String
var body: some View {
Text("\(choice)을 선택하셨습니다. ")
}
}

이제 ContentViewNavigationViewText, NavigationLink등을 추가해줍니다.

swift
UNFOLDED
import SwiftUI
struct ResultView: View {
var choice: String
var body: some View {
Text("\(choice)을 선택하셨습니다. ")
}
}
struct ContentView: View {
var body: some View {
NavigationView {
VStack(spacing: 30) {
Text("당신은 동전을 던질것입니다\n앞면 과 뒷면 중에 하나를 선택해 주세요.")
.multilineTextAlignment(.center)
NavigationLink(destination: ResultView(choice: "앞면")) {
Text("앞면을 선택하셨습니다.")
}
NavigationLink(destination: ResultView(choice: "뒷면")) {
Text("뒷면을 선택하셨습니다.")
}
}
.navigationBarTitle("Navigation")
}
}
}

 

아래 코드와 같이 NavigationLink 내에서 Image를 넣어주면 자동으로 텍스트와 모든 것을 파란색으로 설정하게 됩니다.

이것은 때때로 유용할 수 도 있지만, 그렇지 않은 경우가 더 많이 있습니다. 

swift
UNFOLDED
NavigationView {
NavigationLink(destination: Text("Second View")) {
Image("원하는 사진")
}
.navigationBarTitle("Navigation")
}

 만약 사진을 정상적으로 보여주고 싶다면 .renderingMode(.original) 를 Image 밑에 추가해 주면 됩니다.

swift
UNFOLDED
NavigationView {
NavigationLink(destination: Text("Second View")) {
Image("원하는 사진")
.renderingMode(.original)
}
.navigationBarTitle("Navigation")
}

이것의 대안으로는 PlainButtonStyle()과 함께 buttonStyle() 수정자를 사용할 수 있습니다.

swift
UNFOLDED
NavigationView {
NavigationLink(destination: Text("Second View")) {
Image("원하는 사진")
}
.buttonStyle(PlainButtonStyle())
.navigationTitle("Navigation")
}

혹은 button으로 만들어 줄 수 있겠죠.

swift
UNFOLDED
NavigationView {
Button {
// your action here
} label: {
Image("card")
.resizable()
.scaledToFit()
}
.buttonStyle(PlainButtonStyle())
.navigationTitle("Navigation")
}

Environment presentationMode

NavigationLink view에서 Back버튼을 hidden으로 해놓고 따로 버튼을 만들어서 그 버튼을 누르면 메인화면으로 돌아갈 수 있도록 만들어 줄 수도 있습니다. 이것을 사용하기 위해서는 EnvironmentpreseontationMode를 사용 하면 됩니다.

swift
UNFOLDED
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
ScrollView(.vertical, showsIndicators: false) {
Text("some")
Text("some")
Text("some")
}
.navigationBarTitle("네비게이션")
.navigationBarItems(
trailing:
NavigationLink(
destination: secondView(),
label: {
Image(systemName: "person.fill")
.foregroundColor(.red)
})
)
}
}
}
struct secondView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
ZStack(alignment: .topLeading) {
Color.yellow.ignoresSafeArea()
.navigationBarBackButtonHidden(true)
.navigationBarHidden(true)
Button(action: {
presentationMode.wrappedValue.dismiss()
}, label: {
Image(systemName: "xmark")
.imageScale(.large)
.padding()
})
.accentColor(.white)
}
}
}

SwiftUI : NavigationView / NavigationLink - NavigationLink - Environment presentationMode

위에서 나왔던 navigationBarTitle 의 종류에 대해서 먼저 알아보겠습니다.

swift
UNFOLDED
NavigationView {
Text("서근 개발블로그")
.navigationBarTitle("스위프트UI", displayMode: .inline)
}

SwiftUI : NavigationView / NavigationLink - NavigationBarItems /  NavigationBarTitle

automatic / inline / large 3가지가 있고, 기본값이 automatic 인거 같죠? 일단 inline을 먼저 사용해서 화면을 구성해보면,

SwiftUI : NavigationView / NavigationLink - NavigationBarItems /  NavigationBarTitle

여기에 NavigationBarItems을 추가해 봅시다.

SwiftUI : NavigationView / NavigationLink - NavigationBarItems /  NavigationBarTitle

leading / trailing이 있네요. 이제 navigationBarTitle에 아이템을 추가해서 오른쪽, 왼쪽 버튼을 만들어볼게요.

swift
UNFOLDED
NavigationView {
Text("서근 개발블로그")
.navigationBarTitle("스위프트UI", displayMode: .inline)
.navigationBarItems(leading:
Button("왼쪽")
{ /*code*/ }
,trailing: Button("오른쪽")
{ /*code*/ } )

SwiftUI : NavigationView / NavigationLink - NavigationBarItems /  NavigationBarTitle

왼쪽에 버튼을 두 개 추가하고 싶을 땐?

swift
UNFOLDED
NavigationView {
Text("서근 개발블로그")
.navigationBarTitle("스위프트UI", displayMode: .inline)
.navigationBarItems(leading:
HStack {
Button("서근")
{ /*code*/ }
Button("블로그")
{ /*code*/ }
},trailing:
HStack {
Button("구독")
{ /*code*/ }
Button("좋아요")
{ /*code*/ }
}
)
}

SwiftUI : NavigationView / NavigationLink - NavigationBarItems /  NavigationBarTitle

 

뭐.. 버튼이 기본적이지만, 텍스트를 주고 싶다면 가능은 합니다 :)

swift
UNFOLDED
NavigationView {
Text("서근 개발블로그")
.navigationBarTitle("스위프트UI", displayMode: .inline)
.navigationBarItems(leading:
Text("서근"),
trailing:
Text("블로그")
)
}

SwiftUI : NavigationView / NavigationLink - NavigationBarItems /  NavigationBarTitle

SF Symbols.navigationBarItems에 추가해보도록 하겠습니다. 

 

Image로 불러와주고 심볼 아이템을 resizable()해주고 frame()으로 크기를 조절해 주겠습니다.

swift
UNFOLDED
struct DetailView: View {
var body: some View {
Text("서근 개발 블로그")
}
}
struct ContentView: View {
var body: some View {
NavigationView {
Text("사이트")
.navigationBarTitle(Text("홈"))
.navigationBarItems(trailing: NavigationLink(destination: DetailView()){
Image(systemName: "paperplane.circle.fill").resizable()
.frame(width: 30, height: 30, alignment: .trailing)
}
)
}
}
}

SwiftUI : NavigationView / NavigationLink - NavigationBarItems /  NavigationBarTitle

심볼 사이즈를 frame()으로 지정해줄 수 도 있지만 .font(.system(size: CGFloat)) 으로도 가능합니다.

swift
UNFOLDED
NavigationView {
Text("사이트")
.navigationBarTitle(Text("홈"))
.navigationBarItems(trailing: NavigationLink(destination: DetailView()){
Image(systemName: "paperplane.circle.fill").font(.system(size: 30))
}
)
}

Hidden

이밖에도 필요에 따라 NavigationBar 또는 back 버튼을 숨길 수 있습니다.

swift
UNFOLDED
NavigationView {
HStack {
Image(systemName: "person.fill")
Text("서근 개발 블로그")
.navigationTitle("NavigationBarHidden")
.navigationBarHidden(true)
}
}

SwiftUI : NavigationView / NavigationLink - Hidden - navigationBarHidden
navigationBarHidden 수식어 적용 과 미적용 비교

마찬가지로 back 버튼을 숨기려면 원하는 뷰 뒤에 코드를 추가해줘야 합니다.

swift
UNFOLDED
NavigationView {
HStack {
Image(systemName: "person.fill")
Text("서근 개발 블로그")
.navigationTitle("NavigationBarHidden")
.navigationBarItems(trailing: NavigationLink(destination: Text("안녕하세요").navigationBarBackButtonHidden(true)) {
Image(systemName: "star.fill").font(.title)
}
)
}
}

TIP
 
 

navigationBarBackButtonHidden 사용 주의사항
destination으로 가져온 뷰 바로 뒤에 navigationBarBackButton을 추가해줘야 합니다.

 


읽어주셔서 감사합니다🤟

 

 


잘못된 내용이 있으면 언제든 피드백 부탁드립니다.


서근


위처럼 이미지 와 함께 댓글을 작성할 수 있습니다.