[SwiftUI] ObservableObject, ObservedObject, Published

2024. 10. 7. 09:49·Dev/SwiftUI

 

 

 

SwiftUI로 뷰와 로직을 작성하다 보면 데이터 관리에 대한 고민에 부딪히게 된다.

특히 여러 뷰에서 동일한 데이터를 공유하고 업데이트해야 하는 상황에서 State나 Binding만으로는 한계가 있다.

 

이때 Combine 프레임워크의 핵심 요소인

ObservableObject, ObservedObject, 그리고 Published를 이해하는 것이 중요하다.

 

State와 Binding은 주로 상위-하위 뷰 간의 명확한 데이터 흐름에 적합하며, 단일 뷰 내부 또는 계층적으로 연결된 뷰에서 사용하기 좋다. 하지만 외부에 선언된 값을 여러 뷰에서 관찰하고 그 값의 변화에 따라 UI를 업데이트해야 하는 상황에서는 이벤트 변화를 관찰하는 ObservableObject와 ObservedObject가 더 적합하다.

 

 

 


 

 

 

1. ObservableObject: 객체의 변화를 알려줄게!

  • ObservableObject는 객체 내부의 변경 사항이 발생하기 전에 이를 발행(emit)하는 퍼블리셔(publisher)를 가진 타입이다.
  • 변화를 감지할 수 있는 객체를 만들 때 사용한다.
    • ObservableObject를 채택한 클래스의 프로퍼티들을 관찰하고 있다가, 이 프로퍼티의 변화가 감지되면 해당 객체를 사용하는 뷰를 다시 그려 업데이트하는 역할을 수행한다.
  • "이 객체의 값이 바뀌었으니, 업데이트를 진행시켜!" 하고 알리는 역할을 한다.

 

2. Published: 나 값 바뀌었다!

  • Published는 @Published 어트리뷰트로 표시된 프로퍼티의 변경 사항을 발행하는 타입이다.
  • ObservableObject 클래스 내부에 선언될 때, 해당 프로퍼티의 값이 변경되면 자동으로 willSet 역할을 하는 objectWillChange 퍼블리셔를 호출하여 뷰를 업데이트하도록 알린다.
  • 주로 ObservableObject와 함께 사용된다.
  • "나의 값이 바뀌었으니, 뷰를 업데이트해야 해!" 하고 외부에 알리는 역할을 한다.

 

ObservableObject와 Published 사용 예시

class UserSettings: ObservableObject {
  @Published var username = "Anonymous"
  @Published var count = 0
  @Published var isOn = false
}

 

  1. 공식문서에도 따로 강조되어 있는 부분인데, ObservableObject와 Published는 class 내에서만 사용해야한다.
  2. 사용자와 관련된 값을 관찰하기 위해 UserSettings라는 ObservableObject 클래스를 선언했다. 그 안에 관찰하고 싶은 값들을 @Published로 선언했다.
  3. Published로 선언한 username, count, isOn의 값에 변화가 생기는지 시스템이 자동으로 관찰한다.

 

3. ObservedObject: 바뀐 값을 받아서 뷰 업데이트!

  • ObservedObject는 ObservableObject를 따르는 객체를 구독(subscribe)하고, 해당 객체의 상태가 변할 때마다 뷰를 무효화하여 UI를 업데이트하는 프로퍼티 래퍼 타입이다.
  • 뷰 외부에서 생성된 객체의 상태 변화를 구독하고, 그 상태가 변했을 때마다 해당 뷰를 업데이트한다. 
  • "내가 관찰 중이던 값이 바뀌었으니, 이 뷰를 업데이트할게!" 하는 역할을 수행한다.

 

ObservedObject 사용 예시

struct PracticeObservableObject: View {
  
  @ObservedObject var settings = UserSettings()
  
    var body: some View {
      
      VStack {
        
        // MARK: - Change Name
        Text("Hello, \(settings.username)")
        Button(action: {
          settings.username = "New guy"
        }, label: {
          Text("Change Username")
            .labelStyle(.titleOnly)
        })
        
        // MARK: - Change Count
        Text("count: \(settings.count)")
        Button("Add Count") {
          settings.count += 1
        }
        
        // MARK: - Change Value
        Toggle("On", isOn: $settings.isOn)
          .padding(.horizontal, 150)
        Button("Make it On") {
          settings.isOn.toggle()
        }
      }
      
    }
}

 

4. PracticeObservableObject 뷰에서 뷰 외부에서 정의된 settings 객체를 @ObservedObject로 선언하여 구독하고 변화를 관찰한다.

5. 버튼 액션에 따라 settings 객체 내부의 @Published 프로퍼티 값이 변화하면, @ObservedObject를 통해 이 변화를 감지하고 자동으로 뷰를 업데이트한다.

 

시뮬레이터 결과

 

 

 

 

 

 

 


 

References

https://developer.apple.com/documentation/Combine/ObservableObject

 

ObservableObject | Apple Developer Documentation

A type of object with a publisher that emits before the object has changed.

developer.apple.com

 

https://developer.apple.com/documentation/swiftui/observedobject

 

ObservedObject | Apple Developer Documentation

A property wrapper type that subscribes to an observable object and invalidates a view whenever the observable object changes.

developer.apple.com

 

https://developer.apple.com/documentation/combine/published

 

Published | Apple Developer Documentation

A type that publishes a property marked with an attribute.

developer.apple.com

 

https://www.kodeco.com/books/swiftui-cookbook/v1.0/chapters/2-understanding-observableobject-observedobject

 

SwiftUI Cookbook, Chapter 2: Understanding ObservableObject & ObservedObject

Learn how to use the ObservableObject and ObservedObject property wrappers in SwiftUI for shared state management across multiple views.

www.kodeco.com

 

저작자표시 (새창열림)

'Dev > SwiftUI' 카테고리의 다른 글

[SwiftUI] LifeCycle  (1) 2024.10.14
[SwiftUI] Navigation  (0) 2024.09.24
[SwiftUI] scrollTargetLayout과 ScrollTargetBehavior  (0) 2024.08.16
[SwiftUI] Property Wrapper 총정리  (0) 2024.07.26
[SwiftUI] Frame  (0) 2024.07.22
'Dev/SwiftUI' 카테고리의 다른 글
  • [SwiftUI] LifeCycle
  • [SwiftUI] Navigation
  • [SwiftUI] scrollTargetLayout과 ScrollTargetBehavior
  • [SwiftUI] Property Wrapper 총정리
Callie_
Callie_
  • Callie_
    CalliOS
    Callie_
  • 전체
    오늘
    어제
    • 분류 전체보기
      • APPLE
      • Dev
        • Swift
        • UIKit
        • SwiftUI
        • Issue
        • 구현
      • Design
        • HIG
      • CS
      • 직관로그 (출시앱)
        • 업데이트
      • 🌱 SeSAC iOS 3기
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Info탭
    Entry Point
    .fullScreen
    cs
    TableViewCell
    TapGestureRecognizer
    Enum
    layer.shadow
    IBAction
    cornerradius
    화면전환
    Button
    clipsToBound
    Swift
    keyboard
    ios
    네트워크통신
    후기
    tag
    DidEndOnExit
    .OverFullScreen
    addTarget
    modalPresentStyle
    생명주기
    SwiftUI
    stroyboard
    SeSAC
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
Callie_
[SwiftUI] ObservableObject, ObservedObject, Published
상단으로

티스토리툴바