인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

ycc3819님의 프로필 이미지

작성한 질문수

Part2: 초중급 iOS 인스타그램 클론(SwiftUI, MVVM, Firebase, 2024)

58. 다른 사람의 ProfileView 이동 구현

ProfileView에서 toolbar이용시 문제점 발생, 로직이 이해가 되지 않습니다.

해결된 질문

작성

·

60

0


    var body: some View {
        NavigationStack {
            ScrollView { }
        }
        .navigationBarBackButtonHidden()
        .toolbar {
            ToolbarItem(placement: .topBarLeading) {
                Button {
                    dismiss()
                } label: {
                    Image(systemName: "arrow.backward")
                    .tint(.black)
                }
            }
        }  //:TOOLBAR

위와 같이 ProfileView에서 body를 정의하셨는데,

NavigationStack에 toolbar가 항상 나타나는 것으로 이해가 됩니다.

그렇다면, 앱을 실행하고 바로 Profile tab을 누른다면,

image.png

 

.toolbar가 자동으로 생성되면서 dismiss()가 작동하지 않는 toolbar가 생기는 상황이 발생했습니다.

다시 FeedView로 돌아가면 기존 toolbar는 없어지지 않은채로 "<- : arrow.backward" 가 나타나고,

FeedView에서 .overlay { } 로 정의된 NavigationLink를 클릭한다면

toolbar가 두개 생기는 것을 확인할 수 있었습니다.

 

두 개중 위의 버튼은 작동하지 않으며, 아래의 버튼을 누르면 dismiss()가 작동하여 Stack에 쌓인

ProfileView가 없어지면서 FeedView로 돌아가는 것을 확인할 수 있었습니다.

image.png

 

상황에 따라 toolbar가 보일 수 있도록 따로 설정을 해야하는 것일까요?

다시 말해, ProfileView를 Profile을 tab하여 이동하는 경우는 .toolbar가 나타나지 않도록 해야하는 걸까요?

 

 

답변 1

0

애구마(agmma)님의 프로필 이미지
애구마(agmma)
지식공유자

안녕하세요 ycc3819님
먼저 강의 수강해 주셔서 감사합니다.

먼저 toolbar에 작동 원리에 대해 설명드릴게요

.navigationbarBackButtonHidden()과 .toolbar {}는 이 코드가 적힌 화면이 '네비게이션 스택안에 쌓인다면' 해당 화면에서 백버튼을 지우고, 새로운 툴바아이템을 보여줍니다.

 

아래 코드에서 navigationBarBackButtonHidden과 toolbar에 의미는

현재 네비게이션 스택에 쌓이는 모든 화면에 백버튼을 없애고, 툴바를 이걸로 대체해줘 라는 의미가 아니고

현재 화면이 다른 네비게이션 스택안에 쌓인다면 현재화면에 대해서 백버튼을 없애고, 툴바를 대체해줘 라는 의미가 됩니다.

 var body: some View {
        NavigationStack {
            ScrollView { }
        }
        .navigationBarBackButtonHidden()
        .toolbar {
            ToolbarItem(placement: .topBarLeading) {
                Button {
                    dismiss()
                } label: {
                    Image(systemName: "arrow.backward")
                    .tint(.black)
                }
            }
        }  //:TOOLBAR

 

NaviagtionStack과 navigationBarBackButtonHidden(or toolBar)는 별개라고 생각해주시면 됩니다.

 

이 코드를 해석해 본다면

NaviagtionStack : 이 화면은 navigationStack을 통해 다른 화면으로 전환이 되겠구나

navigationBarBackButtonHidden(or toolBar): 이 화면이 다른 navigationStack안에 쌓인다면 기존 백버튼이 사라지고 새 백버튼이 생기겠구나 라고 생각하시면 됩니다.

 

좀더 이해하기 쉽게 다른 코드를 보여드릴게요

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        NavigationStack {
            VStack {
                Text("This is the First View")
                NavigationLink("Go to Second View") {
                    SecondView()
                }
            }
            .navigationTitle("First View")
                
        }
    }
}

struct SecondView: View {
    @Environment(\.dismiss) var dismiss
    
    var body: some View {
        VStack(spacing: 20) {
            Text("This is the Second View")
        }
        .navigationBarBackButtonHidden()
        .toolbar {
            ToolbarItem(placement: .topBarLeading) {
                Button {
                    dismiss()
                } label: {
                    Image(systemName: "arrow.backward")
                        .tint(.black)
                }
            }
        }
    }
}

#Preview {
    ContentView()
}

 

이 코드는 NavigationStack과 백버튼관련코드가 다른 뷰로 나뉘어져 있는데요.

보통은 이런식으로 쓰이는게, 제 코드에서는 프로필뷰가 2가지 역할을 하기때문에 한곳에 모여있어서 혼란을 야기한것 같습니다.

  1. 프로필뷰 -> 프로필에디팅뷰로 이동하기 위해 NavigationStack을 사용했고요

  2. 피드뷰 -> (다른사람의)프로필뷰로 이동되었을때 백버튼을 바꾸기 위해,
    .navigationBarBackButtonHidden()

     

    .toolbar {}

이 두코드를 사용했다고 보시면 됩니다.


그런데 질문자님처럼 저렇게 화살표가 2개 나오는 상황이 제코드에서는 발생하지 않는거 같은데요.

chapter12폴더에 12-2코드로 한번 실행해보시겠어요?

아마 코드가 다른 부분이 있어서 저런 현상이 나타난게 아닌가 싶습니다.

ycc3819님의 프로필 이미지
ycc3819
질문자

강사님께서 말씀해주신 대로 저도 그렇게 이해하고 있었습니다.

Xcode상 오류일 수 있을까요?

ProfileView에서 마지막. Navigation Stack { } 에 적용하는 부분을 주석처리 해보았습니다.

        NavigationStack { }
        //.navigationBarBackButtonHidden()
        //.toolbar {
        //    ToolbarItem(placement: .topBarLeading) {
        //        Button {
        //            print("?????")
        //            dismiss()
        //        } label: {
        //           Image(systemName: "arrow.backward")
        //            .tint(.black)
        //        }
        //    }
        //}  //:TOOLBAR

 

그 경우에 Stack으로 만들어진 ProfileView의 경우 <Back버튼이 활성화되며,

image.png

 

접속한 아이디의 Profile Tab을 클릭하여 ProfileView로 이동하게 되면,

image.png

 

Stack에 쌓인 View가 아니기 때문에, <Back 버튼이 생기지 않은 것을 확인 할 수 있었습니다.

 

그런데 일부 주석해제를 하고 toolbar를 만든다면,

<Back 버튼이 생긴 곳에서만 toolbar가 만들어져야 하는 것을 아닐까요?

NavigationStack { }
//        .navigationBarBackButtonHidden()
        .toolbar {
            ToolbarItem(placement: .topBarLeading) {
                Button {
                    print("?????")
                    dismiss()
                } label: {
                    Image(systemName: "arrow.backward")
                    .tint(.black)
                }
            }
        }  //:TOOLBAR

위를 구현해본 결과 Profile Tab을 눌러 나온 ProfileView의 결과는 다음과 같습니다.

image.png

 

 

강사님께서 말씀하신 12-2 코드를 적용해도 같은 결과가 나오네요^^;;

ㅠㅠ 다른 방법을 찾아보도록 하겠습니다.

 

애구마(agmma)님의 프로필 이미지
애구마(agmma)
지식공유자

흑 이상하네요

agmma5000@gmail.com
여기로 프로젝트 압축해서 보내주시겠어요? 제가 한번 살펴볼게요

그리고 지금 xcode버전도 알려주세요
xcode에서 ctrl + command + v 누르면 볼 수 있습니다.

ycc3819님의 프로필 이미지

작성한 질문수

질문하기