Open Do-hyun-Kim opened 1 year ago
클래스 오브젝트의 프로퍼티(Key
)에 대한 값(Value
)의 변화를 감지(Observing
)할 수 있는 Cocoa 프로그래밍 패턴이다.
NSObject
를 상속해야 한다.KVO 를 구현 하기 위해서는 NSObject
클래스를 상속받아야 한다. '상속'받아야 하기 때문에 class에서만 구현할 수 있다.
class Observed: NSObject {
...
}
NSKeyValueObserving
프로토콜을 기반으로 동작한다.NSObject
클래스는 NSKeyValyeObserving
프로토콜을 채택/준수(구현)하고 있다.*NSKeyValueObserving
: KVO 구현을 위한 프로토콜이다. Swift에서는 공식적으로 지원하지 않는 프로토콜이다.
dynamic
키워드를 사용해야 한다.dynamic
키워드는 Objective-C 런타임에서 dynamic dispatch
를 동작시켜주는 Objective-C 의 키워드이다.@objc
키워드 역시 붙여 주어야 한다.dynamic
으로 선언하면 해당 프로퍼티를 키패스(KeyPath = /.
)로 사용하여 프로퍼티의 메모리상 주소를 찾을 수 있게 된다.class Observed: NSObject {
@objc dynamic var value: String = ""
}
observe(_ keyPath:options:changeHandler:)
를 사용하여 관찰한다.class가 NSObject
를 상속하였고, dynamic
키워드로 관찰할 수 있는 프로퍼티 역시 설정하였다면 observe(_keyPath:options:changeHandler:)
메서드를 호출하여 프로퍼티를 관찰할 수 있다.
class Observed: NSObject {
@objc dynamic var observedProperty: String = ""
}
var observedObj = Observed()
observedObj.observe(\.observedProperty, options: [.initial, .new, .old, .prior]) { obj, observedProperty in
print("newValue: ", observedProperty.newValue)
print("oldValue: ", observedProperty.oldValue)
print("isPrior: ", observedProperty.isPrior)
}
observe(_ keyPath:options:changeHandler:)
keyPath: KeyPath<Observed, Value>
: dynamic
키워드로 선언된 관찰할 프로퍼티options: NSKeyValueObservingOptions
: 관찰할 프로퍼티에 대한 옵션 값.
.initial
: 초기값 관찰.new
: 값 수정시, 새로운 값 관찰, 생략시 .old
: 값 수정시, 이전 값 관찰.prior
: 값 수정시, 값의 변화에 대한 상태(willChange)를 관찰changeHandler: (Oberved, NSKeyValueObservedChange<Value>) -> Void
: 값 수정시 관찰할 수 있는 클로저
NSKeyValueObservingOptions.new
생략시 NSKeyValueObservedChange<Value>.newValue
는 nil
NSKeyValueObservingOptions.old
생략시 NSKeyValueObservedChange<Value>.oldValue
는 nil
NSKeyValueObservingOptions.initial
생략시 초기값 관찰하지 않음NSKeyValueObservingOptions.prior
생략시 NSKeyValueObservedChange<Value>.isPrior
값은 항상 false
@objc dynamic
을 붙여서 사용한다\.변수명
과 같은 형식으로 넣어준다.new
, .old
, .initial
, .prior
를 넣을 수 있다.
import Foundation
// observe 하려는 프로퍼티에 @objc attribute와 dynamic modifier를 추가해야 한다. class Address: NSObject { @objc dynamic var town: String
init(town: String) {
self.town = town
}
}
// observer 필요 : observe 하려는 프로퍼티가 변경되는지 봐야하기 때문 // observer 추가 : .town // 변경사항이 필요하지 않으면 options 안 주면 됨 -> nil이 출력됨 var address = Address(town: "Seoul")
address.observe(.town, options: [.old, .new, .initial]) { (object, change) in print(change.oldValue, change.newValue) print("****") }
// address의 town 값 변경 address.town = "Jeju" address.town = "London" address.town = "Paris"
/* 결과 < .old, .new, .initial 일 때> nil Optional("Seoul")
Optional("Seoul") Optional("Jeju")
Optional("Jeju") Optional("London")
Optional("London") Optional("Paris")
< .old, .new, .prior 일 때> Optional("Seoul") nil
Optional("Seoul") Optional("Jeju")
Optional("Jeju") nil
Optional("Jeju") Optional("London")
Optional("London") nil
Optional("London") Optional("Paris")
*/
### 장점
- 프로퍼티가 변경될 때마다 알람을 보내도록 자체 스키마를 구현할 필요가 없다
- 객체의 구현을 변경하지 않고 외부에서 내부 객체의 상태 변화에 대응할 수 있다
- 관찰된 프로퍼티의 이전값(oldValue)과 최신값(newValue)를 제공한다
### 단점
- NSObject를 상속받는 객체에서만 사용이 가능하다
- Objective-C 런타임에 의존하기 때문에 순수한 Swift 코드에서는 좋지 않다
### 📝 참고
- [Apple Developer doc - Using Key-Value Observing in Swift](https://developer.apple.com/documentation/swift/using-key-value-observing-in-swift)
- [ZeddiOS - Key-Value Observing(KVO) in Swift](https://zeddios.tistory.com/1220)
- [동동이 - SWIFT KVO Key - Value - Observing](https://dongminyoon.tistory.com/70)
- [KVO에 대해 알아보고 적용해 보자 !!](https://hereismyblog.tistory.com/11)
- [Rhyno's DevLife Log - Key-Value Observing(Key-Value Observing)](https://jcsoohwancho.github.io/2019-11-30-KVO(Key-Value-Observing)/)
class SomeClass: NSObject {
@objc dynamic var value: String = ""
}
let someObject = SomeClass()
someObject.observe(\.value) { (object, change) in
print("SomeClass object value changed to \(object.value)")
}
someObject.value = "test" // TEST
KVO 동작 방식에 대해 설명하시오.
KVO 이란?
NSObject
를 상속한 클래스에서만KVO
를 사용 할 수 있다.KVO 사용 방법
NSObject
를 상속 받도록 한다.Property
에@objc
속성과,dynamic
키워드를 부여한다.observe(_:options:changeHandler:)
를 호출하여 Observing을 수행한다.KVO Options
KVO 장점
old Value
), 변경 후(new Value
) 를 관찰 할 수 있다.KVO 단점
dynamic
키워드로 인해 dynamic Dispatch로 활성화 하게 된다.NSObject
를 상속한class
에서만 사용이 가능하다.📝 참고 사이트