프로그래밍공부(Programming Study)/IOS 개발

SwiftUI에서 Hashable 프로토콜과 ObservableObject, StateObject, EnvironmentObject, Published, State, Binding 어노테이션의 역할

Chann._.y 2024. 10. 20.
728x90

1. Hashable 프로토콜의 역할

개념:
Hashable 프로토콜은 Swift에서 객체를 해시할 수 있도록 하는 프로토콜입니다. 이는 객체가 집합(Set)이나 딕셔너리(Dictionary)의 키로 사용될 수 있게 해줍니다. Hashable을 구현하면 객체의 고유성을 정의하고 데이터 구조에서 쉽게 관리할 수 있습니다.

특징:

  • HashableEquatable을 상속받습니다.
  • hash(into:) 메서드를 구현하여 객체의 해시 값을 생성합니다.
struct Person: Hashable {
    let id: Int
    let name: String

    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
        hasher.combine(name)
    }
}

2. ObservableObject의 역할

ObservableObject는 SwiftUI에서 상태 변화를 알릴 수 있는 클래스에 적용되는 프로토콜입니다. 클래스 내부에서 @Published 속성이 변경되면 뷰는 자동으로 업데이트됩니다.

class UserSettings: ObservableObject {
    @Published var username: String = "Guest"
}

3. StateObject의 역할

StateObject는 SwiftUI에서 상태 객체의 생명 주기를 관리하는 어노테이션입니다. 뷰가 재생성될 때도 상태를 유지하며, 초기화가 필요한 경우 사용됩니다.

struct ContentView: View {
    @StateObject var userSettings = UserSettings()

    var body: some View {
        Text("Hello, \(userSettings.username)")
    }
}

4. EnvironmentObject의 역할

EnvironmentObject는 전역적인 데이터를 공유할 때 사용됩니다. 상위 뷰에서 하위 뷰로 데이터를 전달하며, 같은 환경 내에서 여러 뷰가 공유된 데이터를 사용할 수 있습니다.

class AppSettings: ObservableObject {
    @Published var theme: String = "Light"
}

struct ContentView: View {
    @EnvironmentObject var settings: AppSettings

    var body: some View {
        Text("Current theme: \(settings.theme)")
    }
}

5. Published 어노테이션의 역할

@PublishedObservableObject와 함께 사용되어 프로퍼티 값이 변경될 때 자동으로 알림을 트리거합니다. 이로 인해 UI가 자동으로 업데이트됩니다.

class Counter: ObservableObject {
    @Published var count = 0
}

6. State의 역할

개념:
@State는 뷰 내부에서 로컬 상태를 관리하는 데 사용되는 속성 래퍼입니다. 값이 변경될 때마다 뷰가 자동으로 다시 렌더링됩니다.

특징:

  • 뷰의 로컬 상태를 관리하며, 상태가 변경될 때마다 해당 뷰가 갱신됩니다.
  • 뷰 외부에서 접근할 수 없으며, 해당 뷰의 생명 주기 동안 상태가 유지됩니다.

구체적인 예:

struct ContentView: View {
    @State private var isOn: Bool = false

    var body: some View {
        Toggle("Switch", isOn: $isOn)
    }
}

7. Binding의 역할

개념:
@Binding은 상태를 다른 뷰에 전달하거나, 상위 뷰와 하위 뷰 간의 데이터 공유를 가능하게 하는 속성 래퍼입니다. 주로 입력 값 등을 상위 뷰에서 관리할 때 유용합니다.

특징:

  • 상위 뷰에서 관리되는 상태 값을 하위 뷰로 전달하여 하위 뷰가 직접 해당 값을 수정할 수 있습니다.
  • 상태 값을 직접 소유하지 않고 참조만 하므로 값의 양방향 바인딩이 가능합니다.

구체적인 예:

struct ToggleView: View {
    @Binding var isOn: Bool

    var body: some View {
        Toggle("Switch", isOn: $isOn)
    }
}

struct ParentView: View {
    @State private var isToggleOn = false

    var body: some View {
        ToggleView(isOn: $isToggleOn)
    }
}

8. SwiftUI에서의 구체적인 예제

다음은 ObservableObject, StateObject, Published, State, Binding, 그리고 EnvironmentObject를 함께 사용하는 예제입니다.

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

struct ChildView: View {
    @EnvironmentObject var counter: Counter
    @Binding var isCounterVisible: Bool

    var body: some View {
        VStack {
            if isCounterVisible {
                Text("Count: \(counter.count)")
                Button("Increment") {
                    counter.count += 1
                }
            }
        }
    }
}

struct ParentView: View {
    @StateObject var counter = Counter()
    @State private var isCounterVisible = true

    var body: some View {
        ChildView(isCounterVisible: $isCounterVisible)
            .environmentObject(counter)
    }
}

설명:

  • CounterObservableObject를 채택한 클래스이며, @Published로 상태 변화가 있을 때마다 뷰가 업데이트됩니다.
  • ParentView에서 @StateObject로 객체를 생성하고, 하위 뷰인 ChildView로 전달합니다.
  • ChildView에서는 Binding을 통해 상위 뷰의 상태를 수정할 수 있으며, EnvironmentObject로 전달받은 전역 상태 값을 사용할 수 있습니다.
728x90

댓글