SwiftUI - ObservableObject

이재원·2024년 7월 8일
0

SwiftUI

목록 보기
3/9
post-thumbnail

ObservableObject

ObservableObject 프로토콜은 데이터 모델과 뷰 간의 데이터 흐름을 제어하기 위한 프로토콜 입니다.

공식 문서에 나와 있는 글을 번역하면 다음과 같습니다.

“객체가 변경되기 전에 방출하는 게시자가 있는 객체 유형입니다.”

한번에 와 닿지는 않지만 차근차근 알아가 보도록 하겠습니다.

정의는 이렇습니다.

protocol ObseravableObject: AnyObject

클래스 프로토콜입니다. 즉, 이 프로토콜을 따르는 클래스 인스턴스를 관찰하다 어떠한 값이 변경되면 뷰 업데이트를 해줍니다.

공식문서에 나와 있는 코드입니다.

class Contact: ObservableObject {
    @Published var name: String
    @Published var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    func haveBirthday() -> Int {
        age += 1
        return age
    }
}

let john = Contact(name: "John Appleseed", age: 24)
cancellable = john.objectWillChange
    .sink { _ in
        print("\(john.age) will change")
}
print(john.haveBirthday())
// Prints "24 will change"
// Prints "25"

코드를 하나하나 살펴보면 Contact 클래스는 ObservableObject 프로토콜을 따릅니다.

내부에는 @Published 프로퍼티로 선언된 변수가 2개 있는데, @Published는 별도로 다루기로 하겠습니다.

john이라는 Contact 인스턴스를 초기화하여 만들어주고, objectWillChange를 통해 개체의 변경사항이 있기 전에 내보내는 publisher로 탐색해 줍니다.

objectWillChange는 ObservableObject가 사용된 구조체나 클래스의 데이터가 변경될 때마다 뷰에 알리기 위한 특별한 publisher 입니다.

즉, objectWillChange publisher를 사용하면 SwiftUI는 데이터의 변화가 감지될 때마다 뷰를 자동으로 업데이트 할 수 있는데, 이는 SwiftUI 뷰에서 자동으로 제공되므로 ObservableObject를 구현하는 클래스나 구조체에서는 데이터가 변경될 때 objectWillChange publisher를 사용하여 뷰를 업데이트 할 수 있습니다.

따라서 위 예제에서 name과 age가 @Published로 선언되어 있기 때문에 각 변수들의 값이 변경될 때마다 objectWillChange publisher가 자동으로 발생하고, .sink에 등록된 클로저가 실행됩니다.

objectWillChange publisher를 구독한 결과 값으로 cancellable에는 AnyCancellable 인스턴스가 저장됩니다. AnyCancellable은 Swift의 Combine 프레임워크에서 구독(subscribe)을 관리하는 객체로, 구독을 취소할 때 cancel() 메서드를 호출하면 됩니다. 이를 통해 john 객체의 변경 사항을 더 이상 감지하지 않게 할 수 있습니다.

하지만 여기서 주의할 점은 구독을 cancel한다고 해서 john의 age가 24로 돌아가는 것은 아닙니다. 단지 구독을 취소함으로써 앞으로 발생할 변화들을 감지하지 않을 뿐이지 haveBirthday()를 호출하면 여전히 age는 증가합니다.

let john = Contact(name: "John Appleseed", age: 24)
let cancellable = john.objectWillChange
    .sink { _ in
        print("\(john.age) will change")
    }

print(john.haveBirthday())  // Prints: "24 will change" followed by "25"

// 구독 취소
cancellable.cancel()

// 앞으로 발생하는 모든 변화 감지하지 않음
print(john.haveBirthday())  // sink closure 에서 print 되지 않고, age는 26이 됨

print(john.age)  // Prints: 26

ObservableObject 요약

  • ObservableObject
    • 데이터 모델과 뷰 간의 데이터 흐름을 제어하는 프로토콜
    • 클래스 전용 프로토콜
    • 객체가 변경되기 전에 방출하는 objectWillChange 퍼블리셔를 제공
    • SwiftUI에서 데이터 변경 시 뷰를 자동으로 업데이트
    • @Published와 함께 사용하여 프로퍼티 변경 시 objectWillChange를 자동으로 호출
    • Combine 프레임워크의 AnyCancellable로 구독을 관리할 수 있음
    • 구독 취소 시 objectWillChange에 대한 감지 중단 가능

마무리

이렇게 ObservableObject에 대해 알아봤습니다. 다음 포스팅에서는 ObservableObject와 함께 사용하는 PublishedObservedObject에 대해 알아보도록 하겠습니다.

출처
https://developer.apple.com/documentation/Combine/ObservableObject
https://green1229.tistory.com/228
https://jh-make.tistory.com/entry/ObservableObject와-objectWillChange

profile
20학번 새내기^^(였음..)

0개의 댓글