본문 바로가기

iOS/iOS 기술 면접

KVO(Key-Value Observing)

KVO(Key-Value Observing)

  • KVO는 객체의 프로퍼티 변화를 다른 객체에 알리는 Cocoa Programming Pattern
  • 논리적으로 분리된 models과 views 사이의 변경사항을 전달하는데 유용
  • NSObject에서 상속받은 클래스만 사용 가능

바로 코드를 보면서 한번 살펴 보겠습니다~!

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

 

다음과 같은 클래스에서 KVO를 이용해 상태 변화를 감지하고 싶다고 가정해보겠습니다.

KVO를 사용하기 위해서는 우선 다음과 같은 코드를 추가해줘야 합니다.

  1. NSObject 상속
  2. 변화할 프로퍼티에 @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