iOS
[Combine] Chapter12 : Key-Value Observing (KVO)
Peppo
2023. 1. 15. 17:27
728x90
Key-Value Observing
publisher(for:)
단일 변수의 변화를 관찰하려면?
KVO(Key-Value Observing)를 준수하는 객체의 모든 속성에 대한 게시자를 제공합니다.
ObservableObject 프로토콜은 여러 변수가 변경될 수 있는 경우를 처리합니다.
KVO는 Objective-C의 필수 구성 요소였고,
Foundation, UIKit 및 AppKit 클래스 대부분의 프로퍼티는 KVO를 준수합니다.
따라서, KVO를 사용하여 변화를 관찰할 수 있습니다.
KVO를 준수하는 프로퍼티를 관찰하는 방법 (OperationQueue를 이용)
import Combine import Foundation let queue = OperationQueue() let subscription = queue.publisher(for: \.operationCount) .sink { print("Outstanding operations in queue: \($0)") }
KVO를 준수하는 프로퍼티 세팅 및 subscribe
- NSObject를 채택하는 class
- 프로퍼티 앞에 @objc dynamic 키워드 추가.
아래 예시 코드 참고.
// 1 class TestObject: NSObject { // 2 @objc dynamic var integerProperty: Int = 0 } let obj = TestObject() // 3 let subscription = obj.publisher(for: \.integerProperty) .sink { print("integerProperty changes to \($0)") } // 4 obj.integerProperty = 100 obj.integerProperty = 200 //integerProperty changes to 0 //integerProperty changes to 100 //integerProperty changes to 200
1. NSObject 프로토콜을 준수하는 class를 만듭니다.
2. 관찰하고 싶은 프로퍼티 앞에 @objc dynamic 키워드를 붙여줍니다.
3. 변수 integerProperty를 관찰하는 게시자를 subscription 상수로 만듭니다.
4. 프로퍼티를 업데이트 해서 값을 관찰하는걸 확인합니다.
위에도 언급했지만, KVO는 Objective-C 기능이며, Objective-C에 연결된 모든 Swift 유형에서 잘 작동합니다.
+ 추가 테스트
class TestObject: NSObject { @objc dynamic var integerProperty: Int = 0 @objc dynamic var stringProperty: String = "" //추가 @objc dynamic var arrayProperty: [Float] = [] //추가 } let obj = TestObject() let subscription = obj.publisher(for: \.integerProperty) .sink { print("integerProperty changes to \($0)") } obj.integerProperty = 100 obj.integerProperty = 200 //추가 let subscription2 = obj.publisher(for: \.stringProperty) .sink { print("stringProperty changes to \($0)") } let subscription3 = obj.publisher(for: \.arrayProperty) .sink { print("arrayProperty changes to \($0)") } obj.stringProperty = "Hello" obj.arrayProperty = [1.0] obj.stringProperty = "World" obj.arrayProperty = [1.0, 2.0] //integerProperty changes to 0 //integerProperty changes to 100 //integerProperty changes to 200 //stringProperty changes to //arrayProperty changes to [] //stringProperty changes to Hello //arrayProperty changes to [1.0] //stringProperty changes to World //arrayProperty changes to [1.0, 2.0]
debug area를 보면 초기값과 변경된 값들이 나오는걸 확인할 수 있습니다.
publisher(for:options:)
options 파라미터에 .initial, .prior, .old, .new 4가지 값들이 있습니다.
• .initial: 초기값을 방출
• .prior: 값이 변경될 때 '이전 값' 과 '새로운 값' 방출
1. 초기값을 제외하고 싶다면?
options: []
let subscription2 = obj.publisher(for: \.stringProperty, options: []) .sink { print("stringProperty changes to \($0)") } //초기값 제외 //stringProperty changes to Hello //stringProperty changes to World
2. 값이 바뀔때 이전값을 확인하고 싶다면?
options: [.prior]let subscription2 = obj.publisher(for: \.stringProperty, options: [.prior]) .sink { print("stringProperty changes to \($0)") } //stringProperty changes to //stringProperty changes to Hello //stringProperty changes to Hello //stringProperty changes to World
위 방법 보다 더 간단하게 값을 관찰할 수 있는 방법이 있습니다.
ObservableObject
Combine의 ObservableObject 프로토콜은 NSObject에서 파생된 객체뿐만 아니라 Swift 객체에서 작동합니다.
사용법
1. class에 ObservableObject 프로토콜 채택
2. 프로퍼티 앞에 @Published 키워드를 붙이면 끝
import Combine import Foundation class MonitorObject: ObservableObject { @Published var someProperty = false @Published var someOtherProperty = "" } let object = MonitorObject() let subscription = object.objectWillChange.sink { print("object will change") } object.someProperty = true object.someOtherProperty = "Hello World" //object will change //object will change
어떤값이 변경되었는지 알수는 없지만, 값이 변경될때를 알기 때문에 UI업데이트할때 유용하게 쓰일것 같습니다.
(SwiftUI와 잘 맞게 설계되었다고 나와있음)
728x90