개발/swift

[swift] 상태관리도구 (EnvironmentObject, ObservableObject, state)

iris3455 2025. 4. 11. 13:09

@EnvironmentObject

정의

  • 앱 전체에서 공유하는 데이터를 선언적으로 접근할 수 있게 도와주는 전역 상태 관리 도구

 

특징

  • 상위에서 한 번 설정하면, 하위 모든 뷰에서 자동 사용 가능
  • 다른 뷰로 넘길 필요 없이 환경을 통해 주입됨
  • 앱 전체에서 공유하는 설정 등에 적합

 

예시 코드

  • ObservableObject 클래스 만들기
class UserSettings: ObservableObject {
    @Published var username: String = "익명"
}
  • 최상단 뷰에 .environmentObject(_:)로 주입
@main
struct MyApp: App {
    var settings = UserSettings()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(settings)
        }
    }
}

 

  • 하위 뷰에서 @EnvironmentObject로 접근
struct ContentView: View {
    @EnvironmentObject var settings: UserSettings

    var body: some View {
        VStack {
            Text("안녕하세요, \(settings.username)님!")
            EditView()
        }
    }
}

struct EditView: View {
    @EnvironmentObject var settings: UserSettings

    var body: some View {
        TextField("이름 입력", text: $settings.username)
            .textFieldStyle(RoundedBorderTextFieldStyle())
            .padding()
    }
}

 

 

 

 

@ObservableObject

정의

  • SwiftUI에서 상태(state)를 저장하고 변경사항을 알릴 수 있는 객체. View와 데이터가 자동으로 연결되어 데이터가 바뀌면 View도 자동으로 업데이트됨.

 

특징

 

  • 클래스 기반 (reference type)
  • @Published 속성이 바뀌면 자동으로 알림
  • 상위뷰에서 하위뷰에 직접 모델을 넘겨줘야 함

 

 

예시 코드

  • ObservableObject 클래스 만들기
import SwiftUI
import Combine

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

 

  • 외부에서 변수 전달받기 
struct CounterView: View {
    @ObservedObject var counter: Counter // 외부에서 전달 받음

    var body: some View {
        VStack {
            Text("카운트: \(counter.count)")
                .font(.largeTitle)

            Button("증가") {
                counter.count += 1
            }
        }
    }
}

 

  • 호출하여 사용
struct ContentView: View {
    @StateObject private var counter = Counter() 

    var body: some View {
        CounterView(counter: counter) // 주입해서 전달
    }
}

 

 

@State

정의

  • SwiftUI 뷰 안에서 값 하나를 기억하고 관리하는 도구

 

특징

  • View 전용 변수
  • 값을 직접 소유함
  • 다른 뷰와 공유하려면 $count로 넘기고 @Binding으로 받아야 함

 

예시코드

  • 기본 사용 코드
struct CounterView: View {
    @State private var count = 0

    var body: some View {
        VStack {
            Text("카운트: \(count)")
                .font(.largeTitle)

            Button("증가") {
                count += 1
            }
        }
    }
}
  • 값을 참조해서 다른 뷰에 넘기고 싶을 땐 달러($) 를 붙이고 받을때는 @Binding을 사용하여 받음
struct MyView: View {
    @State private var isOn = false

    var body: some View {
        Toggle("스위치", isOn: $isOn)
    }
}

struct CardView: View {
    @Binding var isOn: Bool
}