앱을 만들다보면 List NavigationLink를 만들어서 해당 cell을 클릭하면 화면이 전환되는 코드를 작성해야 할 때가 있습니다.
아래는 NavigationLink List의 기본적인 코드 입니다.
@State var list = ["A","B","C"]
var body: some View {
NavigationView{
List{
ForEach(list, id:\.self){ data in
NavigationLink {
Text("Page Name: \(data)")
// .navigationBarBackButtonHidden(true)
} label: {
Text("Go \(data)")
}
}
}
}
}
만약 전환된 페이지의 Back버튼을 없애고 커스텀 하고싶을 때는 어떻게 해야할까 ?
첫번째 시도
처음에는 NavigationLink의 isActive 파라미터를 사용해 보았습니다.
isActive를 사용하기 위해서는 NavigationLink의 destination을 View 컴포넌트가 아닌 새로운 View 로 수정해주어야합니다.
전환되는 페이지는 데이터를 바인딩 받아서 사용해야하기 때문입니다.
struct ContentView: View {
@State var list = ["A","B","C"]
@State var back = false
var body: some View {
NavigationView{
List{
ForEach(list.indices, id:\.self){ data in
NavigationLink(isActive: $back) {
LinkView(data: $list[data], back: $back)
.navigationBarBackButtonHidden(true)
} label: {
Text("Go \(list[data])")
}
}
}
}
}
}
struct LinkView: View{
@Binding var data: String
@Binding var back: Bool
var body: some View{
Text(data)
Button {
back = false
} label: {
Text("back")
}
}
}
isActive는 NavigationLink를 통해 페이지가 전환되었을때 true로 전환됩니다.
BUG
여기서 발생한 버그는 다음과 같습니다.
클릭한 cell과 link의 데이터가 일치하지가 않아요!
왜지? x100 번 생각한 결과 내린 답은 다음과 같습니다.
back을 isActive 활성 변수로 가지는 NavigationLink는 3개 입니다. (A,B,C)
NavigationLink로 전환될 때 back 인스턴스의 값이 true로 바뀌고 뷰가 새로이 랜더링 됩니다.
클릭한 NavigationLink가 아닌 모든 NavigationLink의 isActive가 true가 되므로 랜덤하게 View가 보이게 됩니다.
💡 즉, NavigationLink의 isActive값을 공유하기 때문에 생긴 이슈!
트러블 슈팅
저는 이 현상을 다음과 같이 해결했습니다.
먼저 버그의 원인 @State var back 인스턴스를 사용하지 않습니다.
struct ContentView: View {
@State var list = ["A","B","C"]
var body: some View {
NavigationView{
List{
ForEach(list.indices, id:\.self){ data in
NavigationLink {
LinkView(data: $list[data])
.navigationBarBackButtonHidden(true)
} label: {
Text("Go \(list[data])")
}
}
}
}
}
}
struct LinkView: View{
@Binding var data: String
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View{
Text(data)
Button {
presentationMode.wrappedValue.dismiss()
} label: {
Text("back")
}
}
}
View의 활성 여부를 isActive로 정의하는게 아닌,
전환되는 View 자체의 presentationMode를 사용하여 버튼을 누르면 해당 View를 dismiss하는 방법을 선택했습니다.
그러면 List에서도 NavigationLink의 isActive 파라미터를 사용하지 않아도 됩니다!
더 좋은 해결법이 있다면 공유해주시면 감사하겠습니다 😊
'📱 iOS > SwiftUI' 카테고리의 다른 글
[SwiftUI] @State를 가지는 View의 업데이트 (0) | 2022.10.29 |
---|---|
[SwiftUI] TabView 페이지 이동시 TabBar , NavigationBar Hidden 처리하기 (0) | 2022.08.14 |
디바이스 화면고정 portrait only (0) | 2022.07.25 |
[SwiftUI] Grid속성 (0) | 2022.07.05 |
URLSession을 통해JSON 가져오기 (2) (0) | 2022.07.04 |