iOS 응용 (SwiftUI)

[iOS - SwiftUI] 뷰 데이터 넘기는 방법 (Binding, ObservableObject, EnvironmentObject, @EnvironmentObject)

jake-kim 2024. 9. 6. 01:21

뷰 데이터 넘기기

  • parentView -> childView 데이터를 넘겨주는 방법
    • 1) @State와 Binding으로 넘겨주기 (양방향 바인딩)
    • 2) EnvironmentObject를 사용하여 넘겨주기 (양방향 바인딩)

1) @State와 Binding으로 넘겨주기

  • @State 프로퍼리를 부모 뷰에 놓고, 달러 $를 붙여서 자식 뷰에 Binding 형태 프로퍼티를 넘겨주기
  • 양방향 바인딩
    • ChildView에서 childText를 변경하면 parentText도 같이 변경되고, parentText가 변경되면 childText도 변경됨
struct ContentView: View {
    @State private var parentText = "parent_text"
    
    var body: some View {
        VStack {
            Text(parentText)
            
            ChildView(childText: $parentText)
        }
    }
}

struct ChildView: View {
    @Binding var childText: String
    
    var body: some View {
        HStack {
            Text("ChildView: ")
            Text(childText)
        }
    }
}

2) EnvironmentObject를 사용하여 넘겨주기

  • 부모 뷰에서 environmentObject를 사용하여 ObservableObject를 따르는 모델을 하위 뷰로 전달
class ContentViewModel: ObservableObject {
    @Published var text = "abcd"
}

struct ContentView: View {
    @ObservedObject private var viewModel = ContentViewModel()
    
    var body: some View {
        VStack {
        }
        .environmentObject(viewModel)
    }
}
  • 하위뷰에서는 @EnvironmentObject 키워드를 사용하여 전달받아서 사용
struct ContentView: View {
    @ObservedObject private var viewModel = ContentViewModel()
    
    var body: some View {
        VStack {
            ChildView2()
        }
        .environmentObject(viewModel)
    }
}

struct ChildView2: View {
    @EnvironmentObject private var viewModel: ContentViewModel
    
    var body: some View {
        HStack {
            Text("ChildView2: ")
            Text(viewModel.text)
        }
    }
}
  • EnvironmentObject를 사용하면 해당 뷰의 하위 뷰에는 모두 전달되어 또다시 선언하지 않아도 됨
struct ChildView2: View {
    @EnvironmentObject private var viewModel: ContentViewModel
    
    var body: some View {
        HStack {
            Text("ChildView2: ")
            Text(viewModel.text)
            ChildView3()
        }
        .onAppear {
            viewModel.text = "111aaabbbccc"
        }
    }
}

struct ChildView3: View {
    // 최상위 뷰에서 .environmentObject(viewModel) 주입했으므로, childView2에서 주입안해도됨
    @EnvironmentObject private var viewModel: ContentViewModel
    
    var body: some View {
        HStack {
            Text("ChildView3: ")
            Text(viewModel.text)
        }
    }
}
  • 주의사항
    • .environmentObject 주입을 안시켜주면 크래시가 발생하므로 environmentObject가 사라질 가능성이 있는 코드라면 사용을 지양하는것이 좋음

* 참고

- https://developer.apple.com/documentation/swiftui/environmentobject