KVO

Judy·2022년 4월 26일
0

iOS

목록 보기
4/28

Key-Value Observing

KVO

다른 객체의 프로퍼티가 변경되었을 때 바로 알림을 받을 수 있게 하는 메커니즘

MVC 패턴으로 디자인된 애플리케이션에서 뷰, 모델, 컨트롤러의 통신방식이다.
일반적으로 컨트롤러는 모델을 관찰하고, 뷰는 모델 또는 컨트롤러를 관찰한다.

UIKit 프레임워크의 Class는 KVO를 지원하지 않지만 커스텀 뷰나 사용자 정의 개체에서 KVO를 구현할 수 있다.

KVO를 통해 한 개체가 단일 프로퍼티 또는 여러 관계를 가진 프로퍼티를 관찰할 수 있다. 개체는 프로퍼티의 현재 값과 이전 값을 알 수 있다. 여러 관계를 가진 프로퍼티는 변경사항 뿐만 아니라 변경과 관련된 개체도 알 수 있다.

KVO는 NSNotificationNSNotificationCenter 클래스의 메커니즘과 비슷하다. 관찰자로 등록된 모든 개체에게 브로드캐스트로 알리는 NSNotification과 달리, KVO는 프로퍼티가 변경될 때 관찰자로 직접 이동한다.

KVO 구현

NSObject는 KVO의 기본 구현을 제공해서 사용자가 재정의할 사항을 드믈다. 모든 CoCoa의 개체는 본질적으로 KVO가 가능하다.

KVO 알람을 받으려면

  • 관찰되는 클래스가 관찰하려는 프로퍼티에 대해 KVO를 준수하는지 확인
    KVO 준수를 위해서는 관찰되는 클래스도 KVC를 준수해야 하고, 프로퍼티데 대한 자동 알림을 허용하거나 수동으로 구현해야 한다.

  • 값이 변경될 수 있는 개체에 addObserver(_:forKeyPath:options:context:)를 이용해 관찰자 추가하기 (관찰자는 애플리케이션에 있는 다른 개체여야 함)

  • 관찰자 개체에 observeValueForKeyPath:ofObject:change:context: 메서드 구현하기. 관찰하는 프로퍼티가 변경되면 이 메서드가 호출된다.

사용법

NSObject를 상속한 클래스에서만 KVO를 사용할 수 있다.

관찰할 프로퍼티 표시하기

@objc 속성과 dynamic 수식어를 사용해 관찰하려는 프로퍼티를 표시한다.

class MyObjectToObserve: NSObject {
    @objc dynamic var myDate = NSDate(timeIntervalSince1970: 0) // 1970
    func updateDate() {
        myDate = myDate.addingTimeInterval(Double(2 << 30)) // Adds about 68 years.
    }
}

위 예제에서는 myDate 프로퍼티를 관찰할 수 있는 MyObjectToObserve 클래스를 정의했다.

관찰자 클래스의 인스턴스는 하나 또는 여러 프로퍼티의 변화를 관찰할 수 있다. 관찰자를 생성할 때 관찰하려는 프로퍼티의 key pathobserve(_:options:changeHandler:) 메서드를 통해 관찰을 시작할 수 있다.

관찰자 정의하기

class MyObserver: NSObject {
    @objc var objectToObserve: MyObjectToObserve
    var observation: NSKeyValueObservation?
    
    init(object: MyObjectToObserve) {
        objectToObserve = object
        super.init()
        
        observation = observe(
            \.objectToObserve.myDate,
            options: [.old, .new]
        ) { object, change in
            print("myDate changed from: \(change.oldValue!), updated to: \(change.newValue!)")
        }
    }
}

위 예제에서는 \.objectToObserve.myDate key pathMyObjectToObservemyDate를 참조한다.

NSKeyValueObservedChangeoldValue, newValue 프로퍼티를 통해 관찰 중인 프로퍼티의 변경사항을 확인할 수 있다.

만약 프로퍼티의가 어떻게 변했는지 알 필요가 없다면 option 매개변수를 생략하면 된다. 그럼 oldnew를 저장하지 않아 oldValuenewValuenil이 된다.

프로퍼티와 관찰자 연결

let observed = MyObjectToObserve()
let observer = MyObserver(object: observed)

관찰자 이니셜라이저로 개체를 전달해 관찰자하려는 프로퍼티와 관찰자를 연결한다.

프로퍼티 변경에 응답하기

연결된 프로퍼티가 변경되면 자동으로 관찰자의 변경 핸들러가 트리거되어 알 수 있다.

myDate.변경 
// Prints "myDate changed from: 1970-01-01 00:00:00 +0000, updated to: 2038-01-19 03:14:08 +0000"

Notification vs KVO

Notification

장점

  • 간편하게 구현 가능
  • 다수 객체들에게 동시에 알려줄 수 있음

단점

  • 추적이 쉽지 않음
  • Notification post 이후 정보를 알 수 없음

KVO

장점

  • new/old 값을 쉽게 알 수 있음
  • 두 객체 사이 정보를 맞추기 쉬움

단점

  • NSObject를 상속하는 개체만 가능함
  • 메모리에서 해제될 때 옵저버를 지워줘야 함
  • 많은 value를 감시하는 조건문 필요




참조
Apple Developer - KVO
Apple Developer - Using Key-Value Observing

profile
iOS Developer

0개의 댓글