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와 함께 사용하는 Published
와 ObservedObject
에 대해 알아보도록 하겠습니다.
출처
https://developer.apple.com/documentation/Combine/ObservableObject
https://green1229.tistory.com/228
https://jh-make.tistory.com/entry/ObservableObject와-objectWillChange