스유를 써봐유!

NavigationView, NavigationLink

Aiden Jang 2021. 9. 26. 02:38
728x90
반응형

 

 

 

 

 

 

안녕하세요. iOS 개발자 에이든입니다!👦🏻

 

 

 

이번 스유를 써봐유 시간은~

iOS App을 보면 TabBar와 함께 자주 쓰이는 NavigaionView!

그리고 NavigationView의 이동을 위해 사용되는 NavigationLink에 대해 알아보겠습니다.

 

 

 

NavigationView의 Bar에 대한 설명은 워낙 커스텀 방법이 많고 다양해서 따로 다뤄보도록 할게요!

그럼 일단 이 둘을 먼저 파헤쳐봅시다!

 


 

먼저 NavigationView의 정의를 살펴볼게요~

Apple Deverloper 사이트에서는

탐색 계층 구조에서 보이는 경로를 나타내는 View의 Stack을 표시하기 위한 View

라고 정의를 내리고 있습니다.

 

쉬운 예시로 기본 App인 Setting을 보시게 되면 

어떤 요소를 터치하면 옆으로 쓱~ 다른 View가 나오면서 다른 정보들을 보여주죠?

 

이것이 바로 NavigationView이고,

최상단에 Setting이라고 적혀있는 Bar가 NavigationBar입니다

그리고 View의 이동을 하게 해 주는 것이 바로 NavigationLink죠!

 

그럼 NavigationView, NavigationLink를 구현하는 방법을 알아봅시다!

 

 


NavigationView

예전에 ViewController로 구현할 때에는 UINavagationController를 활용했어요. SwiftUI는 NavigationView를 활용해서 훨씬 간단하게 구현할 수 있습니다!

 

먼저 간단하게 Model을 만들어 주겠습니다!

ModelIdentifiable을 채택하도록 구현했는데, 이는 고유한 id를 부여한다고 보시면 됩니다.

struct Model: Identifiable {
    var id: Int
    var name: String
    var age: Int
    
    init(id: Int, name: String, age: Int) {
        self.id = id
        self.name = name
        self.age = age
    }
}

 

자 Model은 만들었고 이를 바탕으로 App에 들어갈 Data를 만들어 줄게요

let models: [Model] = [ Model(id: 1, name: "토니", age: 25), Model(id: 2, name: "스티븐", age: 27), Model(id: 0, name: "제이미", age: 21)]

 

이제 이를 바탕으로 NavigationView를 만들어 보겠습니다!

struct ContentView: View {
    var body: some View {
        NavigationView {
            List(models) { model in
                Text(model.name)
            }
            .navigationBarTitle("명단")
        }
    }
}

 

어떤가요? 엄청 간단하게 구현되었죠?

주의하실 점!!

NavigationTitle은 꼭 NavigationView의 안쪽에 넣어줘야 합니당! 

 

 

그럼 이제 다른 View도 만들어서 서로 이동되게 해볼까요?

 

 


NavigationLink

NavigationView 내부의 다른 View로 이동하게 해주는 View입니다.

바로 예시를 볼까요?

 

일단 이동할 View를 먼저 만들어 주겠습니다.

이때 이 View는 NavigationView 안에 있는 것이니 해당 View에서 Title을 바꿔줄 수 있어요.

struct DetailView: View {
    var model: Model
    
    var body: some View {
        VStack {
            Image(systemName: "person.circle")
                .resizable()
                .frame(width: 100, height: 100, alignment: .center)
            Text(model.name)
                .font(.system(size: 60))
            Text("\(model.age)세")
                .font(.system(size: 40))
        }
        .navigationTitle("상세내역")
        // NavigationBar에 보이는 Title의 크기를 작게 보이게 설정!
        .navigationBarTitleDisplayMode(.inline)
    }
}

 

그리고 앞서 보여드렸던 NavigationView 예제 코드에 NavigationLink를 넣어볼게요!

destination에는 보여줄 View를 넣고, label에는 터치할 View를 만들어 넣어주면 된답니다.

struct ContentView: View {    
    var body: some View {
        NavigationView {
            List(models) { model in
                NavigationLink(destination: DetailView(model: model), label: {
                    Text(model.name)
                })
            }
            .navigationBarTitle("명단")
        }
    }
}

 

✨짜자잔✨

어때요 무지 간단하죠?

이렇게 NavigaionLink를 활용해서 View 간의 이동을 만들 수 있습니다!

 

 

 

❗️여기서 주의할 점

방금 코드는 List 외에 ForEach도 가능한데요

struct ContentView: View {    
    var body: some View {
        NavigationView {
            VStack {
                ForEach(models, id: \.id) { model in
                    NavigationLink(destination: DetailView(model: model), isActive: $isActive, label: {
                        Text(model.name)
                    })
                }
            }
            .navigationBarTitle("NavigationLink")
        }
    }
}

 

 

NavigationLink가 하나의 View에 여러개가 있게되죠? 그렇게 되면~

 

 

 

 

읔!!!!!

 

 

 

SwiftUI encountered an issue when pushing aNavigationLink. Please file a bug.

 

라는 디버깅 메시지와 함께 저런 식으로 다른 순번이 튀어나옵니다....

이러한 에러가 나오는 이유는 잘 모르겠지만 해결방법은 있답니다!

 

바로 ForEach 마다 NavigationLink를 각각 생성하지 않고

하나로 그 Index만 받아서 NavigationLink를 하는 방법이죠!

(꼭 하나의 View에는 하나의 NavigationLink만 넣어주세요!)

struct ContentView: View {
    
    @State private var isActive: Bool = false
    @State private var selectedModel: Model = Model(id: 0, name: "", age: 0)
    
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: DetailView(model: selectedModel), isActive: $isActive, label: { EmptyView() })
                
                ForEach(models, id: \.id) { model in
                    Spacer().frame(height: 13)
                    Text(model.name)
                        .onTapGesture {
                            selectedModel = model
                            isActive = true
                        }
                }
            }
            .navigationBarTitle("NavigationLink")
        }
    }
}

 

 

 

그럼 아래와 같이 해결이 된답니다~👏🏻👏🏻👏🏻

 

 

 


 

이번 시간에는 NavigationView와 NavigationLink에 대해 알아보았습니다.

이전에 소게 드렸던 TabBar와 NavigationView를 활용하면

거의 App의 큰 틀은 다 만든 거라고 봐도 무방할 정도입니다ㅎㅎ

 

추후에는 좀 더 이들을 세밀하게 커스텀하는 방법들도 올려드릴게요!

혹시라도 부족하거나 잘못된 부분 그리고 질문 있으시면 언제든 댓글 부탁드려요! 감사합니다!👦🏻👋🏻

728x90
반응형