이번 포스트에서는 SwiftUI에서 자주 사용되는 주요 속성 래퍼인 @State, @StateObject, @ObservedObject, @Binding, @EnvironmentObject에 대해 자세히 알아보자.
@State
@State는 뷰의 로컬 상태를 관리하는 데 사용되는 속성 래퍼이다. 뷰가 자신의 상태를 소유하고, 해당 상태가 변경될 때 UI를 자동으로 업데이트합니다.
struct CounterView: View {
@State private var count = 0
var body: some View {
VStack {
Text("Count: \(count)")
.font(.largeTitle)
Button("Increment") {
count += 1
}
}
.padding()
}
}
- 로컬 상태: 뷰 내부에서만 사용되며, 다른 뷰와 공유되지 않음
- 자동 업데이트: 상태가 변경되면 UI가 자동으로 업데이트됨
@StateObject
@StateObject는 뷰가 자신의 상태 객체를 소유하고 초기화할 때 사용된다. 주로 ObservableObject를 준수하는 클래스를 사용할 때 적합하다.
class CounterModel: ObservableObject {
@Published var count = 0
}
struct CounterView: View {
@StateObject private var counter = CounterModel()
var body: some View {
VStack {
Text("Count: \(counter.count)")
.font(.largeTitle)
Button("Increment") {
counter.count += 1
}
}
.padding()
}
}
- 소유권: 뷰가 상태 객체의 소유자
- 초기화: 뷰가 처음 생성될 때만 초기화해야 하며, 이후 상태 변경 시 UI가 자동으로 업데이트됨
@ObservedObject
@ObservedObject는 외부에서 주입된 상태 객체를 관찰하는 데 사용되며, 주로 다른 뷰나 객체에서 상태를 공유할 때 사용된다.
class CounterModel: ObservableObject {
@Published var count = 0
}
struct ParentView: View {
@StateObject private var counter = CounterModel()
var body: some View {
ChildView(counter: counter)
}
}
struct ChildView: View {
@ObservedObject var counter: CounterModel
var body: some View {
VStack {
Text("Count: \(counter.count)")
.font(.largeTitle)
Button("Increment") {
counter.count += 1
}
}
.padding()
}
}
- 외부 주입: 뷰가 상태 객체를 초기화하지 않고, 외부에서 주입받음
- 자동 업데이트: 상태가 변경되면 UI가 자동으로 업데이트됨
@Binding
@Binding은 부모 뷰에서 자식 뷰로 상태를 전달할 때 사용되며, 자식 뷰가 부모의 상태를 직접 수정할 수 있도록 한다.
struct ParentView: View {
@State private var isOn = false
var body: some View {
ToggleView(isOn: $isOn)
}
}
struct ToggleView: View {
@Binding var isOn: Bool
var body: some View {
Toggle("Switch", isOn: $isOn)
.padding()
}
}
- 상태 공유: 부모 뷰의 상태를 자식 뷰에서 직접 수정할 수 있음
- 양방향 데이터 흐름: 부모와 자식 간의 데이터 흐름을 쉽게 관리할 수 있음
@EnvironmentObject
@EnvironmentObject는 앱의 여러 뷰에서 공유되는 상태를 관리하는 데 사용된다. 주로 앱의 전역 상태를 관리할 때 유용하다.
class UserSettings: ObservableObject {
@Published var username: String = "Guest"
}
struct ContentView: View {
@EnvironmentObject var settings: UserSettings
var body: some View {
VStack {
Text("Username: \(settings.username)")
Button("Change Username") {
settings.username = "NewUser"
}
}
.padding()
}
}
// App 구조체에서 환경 객체를 주입
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(UserSettings())
}
}
}
- 전역 상태: 앱의 여러 뷰에서 공유되는 상태를 관리함
- 자동 업데이트: 상태가 변경되면 해당 상태를 사용하는 모든 뷰가 자동으로 업데이트됨
결론
SwiftUI의 속성 래퍼들은 상태 관리와 데이터 흐름을 간편하게 처리할 수 있도록 도와준다. 각 속성 래퍼는 특정한 용도와 특징을 가지고 있으며, 상황에 맞게 적절히 사용하면 더욱 효율적인 UI를 구성할 수 있다.
요약
- @State: 로컬 상태 관리
- @StateObject: 상태 객체의 소유 및 초기화
- @ObservedObject: 외부 상태 객체 관찰
- @Binding: 부모-자식 간의 상태 공유
- @EnvironmentObject: 전역 상태 관리
'걔 (개발)로그 > SwiftUI' 카테고리의 다른 글
| SwiftUI | 중첩된 Navigation Back Button 문제 해결하기 (0) | 2024.08.05 |
|---|---|
| SwiftUI | Firebase Github Login (0) | 2024.07.26 |
| SwiftUI | Luanch Screen(Splash Image) 구현 (0) | 2024.07.23 |