KVC(Key-value coding), KVO(Key-value observing)

2023. 1. 22. 00:01Swift

반응형

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의 두가지 메소드 valueForKeysetValue는 키가 주어질 때 속성의 값을 설정하거나 가져오기 위해 매우 중요한 메소드 이다.
  • NSObject는 기본적으로 위 내용을 제공해준다.
  • KVC를 구현할 때 다음과 같은 내용을 지켜줘야한다.
  1. 클래스는 key와 함께 프로퍼티를 정의해야한다.
  2. 프로퍼티가 변경 가능한 변수일 경우 키 이름을 가진 메소드를 구현해줘야한다.
  3. _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