KVC(Key-value coding), KVO(Key-value observing)
2023. 1. 22. 00:01ㆍSwift
반응형
KVC(Key-value coding), KVO(Key-value Observing)
참고자료
Key-value coding
- KVC란? - 고유 문자열을 사용하여 객체의 속성이나 관계에 간접적으로 접근하는 메커니즘이다.
Object Properties and KVC
- KVC의 핵심은 프로퍼티의 개념이다.
Property
- 프로퍼티는 캡슐화된 객체의 상태단위(unit of state)를 나타낸다. 이런 프로퍼티는 두가지 타입이 있는데 속성(name, title, textColor)과 다른 객체와의 관계가 있다.
- 관계는 일대일 부터 다대다까지 있으며 일대다 다대다의 경우는 array혹은 set이다.
Key
- KVC는 키(고유 문자열 값)를 통한 객체 프로퍼티에 위치해있으며, 해당 키는 대부분 객체에 정의된 인스턴스 혹은 메소드의 이름과 상당부분 일치한다.
- 해당 key는 ASCII코드로 encoding되어야 하며, 시작은 소문자로, 어떠한 공백도 없어야한다.
- 키의 주소는 .(dot)을 통해 구분되는 객체 프로퍼티 접근 방법처럼 문자열을 가지고 있다.
KVC클래스 만들기
NSKeyValueCoding
를 통해 KVC를 만들 수 있다.NSKeyValueCoding
의 두가지 메소드valueForKey
와setValue
는 키가 주어질 때 속성의 값을 설정하거나 가져오기 위해 매우 중요한 메소드 이다.- NSObject는 기본적으로 위 내용을 제공해준다.
- KVC를 구현할 때 다음과 같은 내용을 지켜줘야한다.
- 클래스는 key와 함께 프로퍼티를 정의해야한다.
- 프로퍼티가 변경 가능한 변수일 경우 키 이름을 가진 메소드를 구현해줘야한다.
- _key 혹은 key는 변수 인스턴스를 정의해줘야한다.
KVC 정리
- KVC는 key값을 통해 value를 가져오는 방식이다
- 일반적인
Person.name.firstName
과 같이 직접적으로 접근하여 값을 가져오는 형태가 아닌 간접적으로 가져오는 것이다.
스위프트로 KVO사용하기
- KVO는 코코아 프로그래밍 패턴으로 다른 객체의 프로퍼티가 변경된 것을 알려주는 역할을 한다.
- 모델과 뷰처럼 로직적으로 분리된 곳에서 각각의 변화를 알려줄 필요가 있을 때 유용하다.
- KVO를 사용하기 위해서는 NSObject를 무조건 상속해야한다.
KVO의 어노테이션
- NSObject를 상속하는 것 뿐만이 아닌 관찰할 프로퍼티 혹은 객체에 @objc 및 dynamic을 붙여줘야한다.
class Person: NSObject {
var name: String = "Leon"
@objc dynamic var age: Int = 24
func getOlder() {
self.age += 1
}
}
- 위와 같이 NSObject를 상속해야하며, 관찰하고 싶은 프로퍼티에 @objc와 dynamic 어노테이션을 같이 작성해야한다.
옵저버 정의하기
- 옵저버 클래스의 인스턴스는 하나 혹은 다수의 프로퍼티의 변화에 대한 정보를 관리한다.
- 옵저버를 생성할 때 우리는
observe(_:options:changeHandler:)
메소드를 관찰하는 프로퍼티의 key와 함께 호출한다.
class Observer: NSObject {
@objc var personToObserve: Person
var observation: NSKeyValueObservation?
init(object: Person) {
self.personToObserve = object
super.init()
observation = observe(\.personToObserve.age, options: [.old, .new], changeHandler: { object, change in
print("\(self.personToObserve.name)의 나이가 \(change.oldValue!)에서 \(change.newValue!)로 한 살 먹었습니다.")
})
}
}
- NSKeyValueObservedChange인스턴스의 프로퍼티 oldValue, newValue를 통하여 값의 변화를 확인 할 수 있다.
- 만약 프로퍼티가 어떻게 변화한지에 대하여 필요하지 않다면 observe의 option파라미터를 없애면 된다.
값 변화 확인하기
let leon = Person(name: "Leon")
let mansu = Person(name: "Mansu")
let personObserver = Observer(object: leon)
let otherPersonObserver = Observer(object: mansu)
leon.getOlder()
leon.getOlder()
mansu.getOlder()
/*
Leon의 나이가 24에서 25로 한 살 먹었습니다.
Leon의 나이가 25에서 26로 한 살 먹었습니다.
Mansu의 나이가 24에서 25로 한 살 먹었습니다.
*/
- 위 출력 값을 보면 알 수 있듯이 Person의 age프로퍼티가 변화할 경우 Observer의 changeHandler 클로저가 실행되는 것을 볼 수 있다.
“\” 이것은 도대체 뭘까????
- “\” 백슬래쉬는 keyPath를 지정하기 위한 어노테이션이라고 보면 될 것 같다.
struct Cat {
let name: String
let numberOfLegs: Int
}
let leon = Cat(name: "Leon", numberOfLegs: 4)
print(leon.name) // Leon
print(leon[keyPath: \Cat.name]) // Leon
print(leon[keyPath: \.name]) // Leon
print(leon.name == leon[keyPath: \Cat.name]) // true
print(leon[keyPath: \Cat.name] == leon[keyPath: \.name]) // true
- 아까 KVC에서 말했듯이 위 예제처럼 .(dot)을 이용하여
leon.name
과 같이 직접적으로 접근 할 수도 있지만 keyPath를 이용하여 간접적으로도 접근할 수 있다. - 위와 같이 (백슬래쉬)를 이용하여 keyPath를 사용해 간접적으로도 접근이 가능하다.
반응형
'Swift' 카테고리의 다른 글
Swift 컴파일, 컴파일러 (0) | 2023.02.14 |
---|---|
ARC-간단정리 (0) | 2023.02.07 |
Closures 간단 정리 (2) | 2023.02.06 |
정규표현식(Swift) (0) | 2023.01.29 |
Opaque Types(불투명 타입) 간단하게 훑어보기 (0) | 2023.01.21 |