apple/SwiftUI, Combine

SwiftUI @State @Binding @EnvironmentObject

lgvv 2022. 5. 19. 15:10

SwiftUI @State @Binding @EnvironmentObject

 

SwiftUI를 사용하면서 자주 사용하는 프로퍼티 래퍼인데, Skimming 과정에서 너무 헷갈려서 간단히 정리

 

 

@State: View 내부의 상태가 변경되어서 처리할 때

@Binding: 다른 View에 있는 상태의 변화를 관찰할 때

@EnvironmentObject: View의 계층 관계가 존재할 때 이를 의존성을 갖출 때

 

우선 State와 Binding에 대해서 간단히 보자

아래는 새믈 코드

 

struct FirstView: View {
    @State private var appTitle = tabIndex.first.rawValue
    @State private var count = 0
    
    enum tabIndex: String {
        case first = "1번뷰 입니다."
        case second = "2번뷰 입니다."
        case third = "3번뷰 입니다"
    }
    
    var body: some View {
        TabView {
            VStack {
                Text("스위프트 유아이를 정복해봅시다. count: \(count)")
                    .padding()
                Button {
                    count += 1
                } label: {
                    Text("카운트 업")
                        .foregroundColor(.white)
                        .padding()
                        .background(Color.blue)
                        .cornerRadius(10)
                }
            }
            .tabItem { Label("1번 뷰", systemImage: "pencil.circle") }
            
            SecondView(count: $count)
                .tabItem { Label("2번 뷰", systemImage: "pencil.circle") }
            
            ThirdView(count: $count)
                .tabItem { Label("3번 뷰", systemImage: "pencil.circle") }
        }
    }

}

struct SecondView: View {
    @Binding var count: Int
    
    init(count: Binding<Int> = .constant(0)) {
        _count = count
    }
    
    var body: some View {
        VStack {
            Text("2번뷰입니다. \(count)")
            Button {
                count += 1
            } label: {
                Text("카운트 업")
                    .foregroundColor(.white)
                    .padding()
                    .background(Color.blue)
                    .cornerRadius(10)
            }
        }
        
    }
}

struct ThirdView: View {
    @Binding var count: Int
    
    init(count: Binding<Int> = .constant(0)) {
        _count = count
    }
    
    var body: some View {
        VStack {
            Text("2번뷰입니다. \(count)")
            Button {
                count += 1
            } label: {
                Text("카운트 업")
                    .foregroundColor(.white)
                    .padding()
                    .background(Color.blue)
                    .cornerRadius(10)
            }
        }
    }
}

 

 

스크린샷

아래는 샘플 코드에 대한 스크린 샷

 

 

세개의 뷰

 



1번 뷰는 @State를 가지고 있고 2,3번 뷰는 Binding하고 있어서 1번 뷰의 상태가 변화하면 2번 뷰가 함께 달라짐

동일한 @State에 연결된 @Binding에 값들은 모두 함께 반영됨

 

 

 

@EnvironmentObject에 대해서 살펴보자.

 

사용 순서 정리

  • 1. ObservableObject를 ViewModel에서 상속받기
  • 2. 해당 View에 environment를 사용하여 ViewModel을 넣어주기

 

 

 

샘플 코드

의존성 가져다가 쓸 수 있다.

 

약간 Needle 방향보다는 SwiftInject의 형태와 닮아있다.

 

import Combine
import SwiftUI

class GlobalStore: ObservableObject {
    @Published var count: Int = 0
}

struct EnvironmentSampleView: View {
    var store = GlobalStore()
    
    var body: some View {
        VStack {
            Button(action: {
                store.count += 1
            }, label: { Text("BUTTON") })
            
            ChildView()
                .environmentObject(store)
        }
        
    }
}

struct ChildView: View {
    @EnvironmentObject var store: GlobalStore
    
    var body: some View {
        Text("\(store.count)")
    }
}

 

 

 

 

'apple > SwiftUI, Combine' 카테고리의 다른 글

SwiftUI TextField, SecureField  (0) 2022.05.23
SwiftUI ButtonStyle 적용해보기  (0) 2022.05.23
SwiftUI TabView (Custom TabView)  (0) 2022.05.19
SwiftUI GeometryReader  (0) 2022.05.19
SwiftUI NavigationView  (0) 2022.05.18