다른 객체의 프로퍼티가 변경되었을 때 바로 알림을 받을 수 있게 하는 메커니즘
MVC 패턴으로 디자인된 애플리케이션에서 뷰, 모델, 컨트롤러의 통신방식이다.
일반적으로 컨트롤러는 모델을 관찰하고, 뷰는 모델 또는 컨트롤러를 관찰한다.
UIKit 프레임워크의 Class는 KVO를 지원하지 않지만 커스텀 뷰나 사용자 정의 개체에서 KVO를 구현할 수 있다.
KVO를 통해 한 개체가 단일 프로퍼티 또는 여러 관계를 가진 프로퍼티를 관찰할 수 있다. 개체는 프로퍼티의 현재 값과 이전 값을 알 수 있다. 여러 관계를 가진 프로퍼티는 변경사항 뿐만 아니라 변경과 관련된 개체도 알 수 있다.
KVO는 NSNotification
과 NSNotificationCenter
클래스의 메커니즘과 비슷하다. 관찰자로 등록된 모든 개체에게 브로드캐스트로 알리는 NSNotification
과 달리, KVO는 프로퍼티가 변경될 때 관찰자로 직접 이동한다.
NSObject
는 KVO의 기본 구현을 제공해서 사용자가 재정의할 사항을 드믈다. 모든 CoCoa의 개체는 본질적으로 KVO가 가능하다.
관찰되는 클래스가 관찰하려는 프로퍼티에 대해 KVO를 준수하는지 확인
KVO 준수를 위해서는 관찰되는 클래스도 KVC를 준수해야 하고, 프로퍼티데 대한 자동 알림을 허용하거나 수동으로 구현해야 한다.
값이 변경될 수 있는 개체에 addObserver(_:forKeyPath:options:context:)
를 이용해 관찰자 추가하기 (관찰자는 애플리케이션에 있는 다른 개체여야 함)
관찰자 개체에 observeValueForKeyPath:ofObject:change:context:
메서드 구현하기. 관찰하는 프로퍼티가 변경되면 이 메서드가 호출된다.
NSObject
를 상속한 클래스에서만 KVO를 사용할 수 있다.
@objc
속성과 dynamic
수식어를 사용해 관찰하려는 프로퍼티를 표시한다.
class MyObjectToObserve: NSObject {
@objc dynamic var myDate = NSDate(timeIntervalSince1970: 0) // 1970
func updateDate() {
myDate = myDate.addingTimeInterval(Double(2 << 30)) // Adds about 68 years.
}
}
위 예제에서는 myDate
프로퍼티를 관찰할 수 있는 MyObjectToObserve
클래스를 정의했다.
관찰자 클래스의 인스턴스는 하나 또는 여러 프로퍼티의 변화를 관찰할 수 있다. 관찰자를 생성할 때 관찰하려는 프로퍼티의 key path
로 observe(_:options:changeHandler:)
메서드를 통해 관찰을 시작할 수 있다.
class MyObserver: NSObject {
@objc var objectToObserve: MyObjectToObserve
var observation: NSKeyValueObservation?
init(object: MyObjectToObserve) {
objectToObserve = object
super.init()
observation = observe(
\.objectToObserve.myDate,
options: [.old, .new]
) { object, change in
print("myDate changed from: \(change.oldValue!), updated to: \(change.newValue!)")
}
}
}
위 예제에서는 \.objectToObserve.myDate
key path
가 MyObjectToObserve
의 myDate
를 참조한다.
NSKeyValueObservedChange
의 oldValue
, newValue
프로퍼티를 통해 관찰 중인 프로퍼티의 변경사항을 확인할 수 있다.
만약 프로퍼티의가 어떻게 변했는지 알 필요가 없다면 option
매개변수를 생략하면 된다. 그럼 old
와 new
를 저장하지 않아 oldValue
와newValue
가 nil
이 된다.
let observed = MyObjectToObserve()
let observer = MyObserver(object: observed)
관찰자 이니셜라이저로 개체를 전달해 관찰자하려는 프로퍼티와 관찰자를 연결한다.
연결된 프로퍼티가 변경되면 자동으로 관찰자의 변경 핸들러가 트리거되어 알 수 있다.
myDate.변경
// Prints "myDate changed from: 1970-01-01 00:00:00 +0000, updated to: 2038-01-19 03:14:08 +0000"
참조
Apple Developer - KVO
Apple Developer - Using Key-Value Observing