GGURUPiOS

[Swift] KVO란? Key-Value 코딩과 함께 알아보자 본문

Swift/문법 파헤치기

[Swift] KVO란? Key-Value 코딩과 함께 알아보자

꾸럽 2023. 11. 9. 15:31

안녕하세요

이번시간엔 KVO, KVC에 대해 알아보고,

비교적 잘 정리된 글이 있어 많은부분을 가져왔습니다.

https://anuragajwani.medium.com/introduction-to-kvo-and-kvc-in-swift-dceadfcf1b28 

 


KVO, KVC?

Key-Value ObservingKey-Value Coding은 런타임에 NSObject를 상속하는 클래스의 기본 프로퍼티를 찾아 상호 작용할 수 있도록 하는 메커니즘 (원래는 Objective-C)

컴파일 시 검사하는 점구문 대신 입력된 키를 통해 프로퍼티와 상호 작용할 수 있습니다.

 

아래의 예제를 봅시다.

class Pokemon {
    var name: String
    
    init(name: String) {
        self.name = name
    }
}

let myPokemon = Pokemon(name: "피카츄")

 

포켓몬 인스턴스를 하나 만들고, 피카츄라는 이름을 가진 인스턴스를 한개 생성했습니다

만약 피카츄가 진화를 해서 피츄가 됐다고 생각해볼게요. 

dot문법으로 아래와 같이 변경했다고 칩시다.

myPokemon.name = "피츄"

 

결국 다른 이름으로 바뀌긴 했지만 본질적으로는 동일한 인스턴스 입니다.

그리고 피카츄가 피츄로 변경된 것을 관찰할 수는 없습니다.

 

class Pokemon: NSObject {
    @objc dynamic var name: String
    
    init(name: String) {
       self.name = name
    }
}

 

위와 같이 작성하면 프로퍼티가 KVC 호환성을 가집니다. KVC를 통해 아래와 같은 메서드를 수행할 수 있습니다.

let pokemonName = myPokemon.value(forKey: "name")
myPokemon.setValue("피츄", forKey: "name")

 

애플 문서에서는 아래와 같이 설명합니다

  • NSObject 또는 그 서브클래스 중 하나를 상속하는 Swift 객체는 기본적으로 해당 프로퍼티에 대해 Key-Value Coding을 준수합니다 
  • KVO를 통해 관찰하려는 프로퍼티에는 @objc 속성dynamic 수정자를 사용하여 표시하세요.

즉 우리는 NSObject를 상속받고, 프로퍼티에 @objc dynamic을 선언했으므로 키를 관찰할 수 있게 된겁니다.

준비는 끝났습니다

관찰을 하려면 어떻게 할까요?

바로 인스턴스의 name 변경에 대한 옵저버를 추가하는 것입니다.

let myPokemon = Pokemon(name: "피카츄")

myPokemon.observe(\.name, options: [.old, .new]) { (pokemon, value) in
    print("old name \(value.oldValue)")
    print("new name \(value.newValue)")
}

myPokemon.name = "피츄"

 

위와같이 작성하고 플레이그라운드에서 동작시켜보면 아래와 같이 출력됩니다.


그렇다면 프로퍼티 옵저버와의 차이점은 무엇일까요?

프로퍼티의 상태 변화를 관찰하고 알려줄 수 있다는 점에서 비슷한 기능을 하는 것으로 보이는데요.

 

이러한 상황을 가정해 볼게요. 구글링을 해보니 아래와 같은말이 있던데... 

 

저희가 정의한 타입은 willSet, didSet 등을 구현이 가능합니다.

반면 외부 라이브러리에서 정의한 타입은 저희가 내부소스를 마음대로 변경하지 못합니다.

이런경우에는 KVO를 통해서 관찰해줄 수 있다는 말이 있습니다.

(그런데 그 클래스가 NSObject를 상속받고 프로퍼티가 @objc로 선언되어 있어야 하는거 아닌가?)

= 그 프로퍼티가 KVC호환성을 가져야 하는거 아닌가? 라는 의문이 들었습니다 

 

따라서 아래와 같이 두가지 정도로 정리가 될것 같습니다.

 

  1. 내부코드를 건드리지 않고 외부에서 값의 변화를 관찰하는 것이 가능하다 정도로 이해하는것이 좋을것 같습니다.
  2. 또 다른 큰 차이점은 KVO는 동적 디스패치를 기반으로 속성을 관찰하는 방식입니다.
    didSet/willSet은 정적 디스패치이기 때문에
    옵젝씨의 종속성 또는 레거시코드와의 호환성이 필요한 경우에만 사용하는것을 고려해봅시다. (성능 측면에서 정적 디스패치가 좋기 때문)

 

출처

https://anuragajwani.medium.com/introduction-to-kvo-and-kvc-in-swift-dceadfcf1b28

 

Introduction to KVO and KVC in Swift

Observing and getting notified when properties changes

anuragajwani.medium.com

https://stackoverflow.com/questions/47327363/swift-difference-between-kvo-and-willset-didset

 

Swift: Difference between KVO and willSet & didSet?

I have been working with willSet and didSet for a variable for a while. Its used to get notified and perform some action before and after a variable is changed. I recently came across KVO which does

stackoverflow.com