KVO(Key-Value Observing)
- KVO는 객체의 프로퍼티 변화를 다른 객체에 알리는 Cocoa Programming Pattern
- 논리적으로 분리된 models과 views 사이의 변경사항을 전달하는데 유용
- NSObject에서 상속받은 클래스만 사용 가능
바로 코드를 보면서 한번 살펴 보겠습니다~!
class Person {
var name: String
init(name: String) {
self.name = name
}
}
다음과 같은 클래스에서 KVO를 이용해 상태 변화를 감지하고 싶다고 가정해보겠습니다.
KVO를 사용하기 위해서는 우선 다음과 같은 코드를 추가해줘야 합니다.
- NSObject 상속
- 변화할 프로퍼티에 @objc dynamic 추가
class Person: NSObject {
@objc dynamic var name: String
init(name: String) {
self.name = name
}
}
위 코드를 보시면
Person 클래스는 NSObject를 상속하고 있으며,
@objc dynamic 키워드를 붙힌 name을 KVO의 방식으로 값의 변화를 감시하려고 합니다.
(dynamic은 objective-c 문법으로, 함수, 메서드의 구현을 objective-c 런타임에서 결정하겠다는 의미)
→ 앞전에 한 dynamic Dispatch로 활성화 시키는 의미라고 보면 될듯?
@objc dynamic를 붙힌 것을 보면 아시겠지만 Objective-C 런타임에 의존을 하고 있기 때문에 순수 스위프트 코드로는 좋지 않다고 합니당
아!!하!! NSObject를 상속받아야하니 클래스에서만 구현이 가능하겠네요!!!!!!!!!
이후 프로퍼티의 변화를 감지할 observer를 만들어 줍니다.
var minsu = Person(name: "minsu")
minsu.observe(\.name, options: [.old, .new]) { (object, change) in
print(change.oldValue, change.newValue)
}
minsu.name = "gildong"
// Optional("minsu") Optional("gildong")
- observe(_ keyPath:options:changeHandler:) 메서드를 이용해 감시합니다.
options에 값이 변화 시 어느 시점의 값을 돌려받을지 지정할 수 있습니다.
여기서 보시면 minsu를 gildong으로 변경하니까 observe가 변화를 감지
→ changeHandler가 호출되어서 oldValue, newValue를 가져온 것을 확인할 수 있었습니다.
(참고로 minsu → minsu로 바뀌어도 changeHandler가 호출됩니당)
위 코드를 보면 options: [.old, .new] 가 추가되어 있는데 이를 통해 oldValue, newValue를 받아올 수 있습니다.
options에 올 수 있는 값은 총 4가지 입니다.
new, old, initial, prior
- initial
여기서 initial을 추가하게 된다면 관찰하는 프로퍼티가 초기화 될 때에도 handler가 호출됩니다.
초기활 될 때 : nil → minsu
값 변경 : minsu → gildong
var minsu = Person(name: "minsu")
minsu.observe(\.name, options: [.old, .new, .initial]) { (object, change) in
print(change.oldValue, change.newValue)
}
minsu.name = "gildong"
// nil Optional("minsu")
// Optional("minsu") Optional("gildong")
- prior
단어의 뜻 그대로 직전의 값을 준다는 의미로 보입니다.
출력된 결과로 보아 gildong으로 바뀌었지만 직전의 값인 minsu와 nil을 리턴하는 것을 확인할 수 있습니다.
var minsu = Person(name: "minsu")
minsu.observe(\.name, options: [.old, .new, .prior]) { (object, change) in
print(change.oldValue, change.newValue)
}
minsu.name = "gildong"
// Optional("minsu") nil
// Optional("minsu") Optional("gildong")
몇번 더 변화를 줘보면
var minsu = Person(name: "minsu")
minsu.observe(\.name, options: [.old, .new, .prior]) { (object, change) in
print(change.oldValue, change.newValue)
}
minsu.name = "gildong"
minsu.name = "chulsu"
minsu.name = "young"
// Optional("minsu") nil
// Optional("minsu") Optional("gildong")
// Optional("gildong") nil
// Optional("gildong") Optional("chulsu")
// Optional("chulsu") nil
// Optional("chulsu") Optional("young")
위와 같이 각각 변화를 감지한 후 직전의 값이었던 minsu, gildong, chulsu를 리턴한 것을 볼 수 있습니당
다음으로 볼껀 handler의 파라미터 입니다.
코드에서는 object와 change가 포함되어 있는데 여기서 object는 현대 observe하는 프로퍼티의 타입입니다.
따라서 object.name 으로 접근하여 현재의 name값을 출력할 수 있습니다.
KVO의 특징
- 논리적으로 분리된 두 객체 간 변경사항을 전달 가능 → 동기화
- 객체 내부의 코드 변경없이 외부에서 상태 변화를 감지할 수 있음.
(didset, willset을 사용할 수 없는 환경에서)
두번째꺼가 무슨말이냐면 라이브러리 등에 있는 프로퍼티가 있을 수 있자나여
그 내부에서 옵저버를 추가할 수 없으니 KVO를 통해서 외부에서 변화를 감지할 수 있다 이런거더라구요
근데 KVO도 사용하려면 결국에는 클래스가 NSObject를 상속하고 있어야하고, @objc dynamic 도 붙어야하는데 조건을 만족하기 힘들지 않ㅇ나,,,? 라는 생각도 들긴 합니당
그리고 dynamic을 통해 동적 디스패치로 동작을 하기 때문에 성능상으로도.. 안좋은게 아닌가.. 라는 의문이 듬.
암튼 이상임다!
+) 참고
호오오오오시나 제 블로그의 코드를 쓰시는 분들..
observe를 쓸 때에 let observation 등의 코드를 이용해서 할당을 해주셔야 합니다.
안그러면 시스템이 알아서 remove해버림
변수에 할당해서 메모리상에 유지시켜줘야지 변화를 탐지할 수 있습니다!!
(그래서 사실 공식문서를 봐도 저렇게 전역으로 안쓰구 객체 안에서 사용함, 공식문서 짱)
Key-Value Observing(KVO) in Swift
Key-Value Observing(KVO) in Swift
안녕하세요 :) Zedd입니다. 오늘은 KVO에 대해서 공부! # KVO - Key-Value Observing의 약자 - 객체의 프로퍼티의 변경사항을 다른 객체에 알리기 위해 사용하는 코코아 프로그래밍 패턴 - Model과 View와 같이
zeddios.tistory.com
Using Key-Value Observing in Swift | Apple Developer Documentation
Using Key-Value Observing in Swift | Apple Developer Documentation
Notify objects about changes to the properties of other objects.
developer.apple.com
Key-Value Observing(Key-Value Observing)
Key-Value Observing(Key-Value Observing)
이번 포스트에서는 프로퍼티의 변화를 감시하고 이에 대해 알림을 받아 특정한 동작을 수행하도록 하는 KVO(Key-Value Observing)에 대해서 알아보도록 하겠습니다. KVO란? KVO는 객체의 프로퍼티 변화
jcsoohwancho.github.io
'iOS > iOS 기술 면접' 카테고리의 다른 글
Struct는 뭐고 어떻게 사용할까? (0) | 2023.11.02 |
---|---|
Optional (1) | 2023.11.02 |
AnyObject (0) | 2023.11.02 |
Convenience init (1) | 2023.10.31 |
Copy On Write는 어떤 방식으로 동작할까? (0) | 2023.10.31 |