적당한 고통은 희열이다

- 댄 브라운 '다빈치 코드' 중에서

Swift iOS 앱 개발/Swift

[Cocoa Design Pattern] KVO: Key-Value Observing

hongssup_ 2022. 12. 26. 01:46
반응형
Key-Value Observing이란 객체의 프로퍼티 변경 사항을 다른 객체에 알리기 위해 사용하는 프로그래밍 패턴. 
kvo는 
Swift 상에서는 didSet이나 willSet 같은 것으로 충분히 대체가 가능할 것 같아 굳이 써야하나 싶은 패턴인 것 같다.

KVO: Key-Value Observing 이란?

Cocoa programming pattern you use to notify objects about changes to properties of other objects. It’s useful for communicating changes between logically separated parts of your app—such as between models and views. You can only use key-value observing with classes that inherit from NSObject.

- 객체의 프로퍼티의 변경사항을 다른 객체에 알리기 위해 사용하는 코코아 프로그래밍 패턴

- Model과 View와 같이 논리적으로 분리된 파트간의 변경사항을 전달하는데 유용함

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

 

KVO 사용법

Set Property for Key-Value Observing

관찰할 프로퍼티 설정해주기

Mark properties that you want to observe through key-value observing with both the @objc attribute and the dynamic modifier.

class Company: NSObject {
    @objc dynamic var president: String = "진양철"
    
    func updatePresident(president: String) {
        self.president = president
    }
}

Define an Observer

When you create an observer, you start observation by calling the observe(_:options:changeHandler:) method with a key path that refers to the property you want to observe.

class CompanyObserver {
    var observation: NSKeyValueObservation?
    
    func observe(object: Company) {
        observation = object.observe(\.president, options: [.old, .new]) { object, change in
            print(change.oldValue, change.newValue)
        }
    }
    
    deinit {
        observation?.invalidate()
    }
}

Respond to a Property Change

프로퍼티 변경 감지

다음과 같이 옵저버를 설정해준  후, 프로퍼티를 변경해주면 옵저버 실행이 잘 되는 걸 확인할 수 있다. 

let company = Company()
let observer = CompanyObserver()
observer.observe(object: company)

company.updatePresident(president: "진도준") //회장: 진양철 -> 진도준

 

더보기
class Company: NSObject {
    @objc dynamic var president: String = "진양철"
    
    func updatePresident(president: String) {
        self.president = president
    }
}

class CompanyObserver {
    var observation: NSKeyValueObservation?
    
    func observe(object: Company) {
        observation = object.observe(\.president, options: [.old, .new]) { object, change in
            guard let oldValue = change.oldValue, let newValue = change.newValue else { return }
            print("회장: \(oldValue) -> \(newValue)")
        }
    }
}

let company = Company()
let observer = CompanyObserver()
observer.observe(object: company)

company.updatePresident(president: "진도준") //회장: 진양철 -> 진도준

 

* 프로퍼티 옵저버 (willSet, didSet) 랑 비슷한 것 같은데? 라는 생각이 들었음.

프로퍼티 옵저버는 타입 정의 내부에 위치해야 하고, KVO는 타입 정의 외부에서 observer를 추가할 때 사용하는 거라고 한다. 

즉, 자신이 정의한 타입의 경우 willset, didset 구현으로 편리하게 사용이 가능하지만, 외부 라이브러리를 사용한 경우에는 내부 소스를 변경할 수 없기 때문에 KVO를 활용해 프로퍼티 감시자처럼 사용할 수 있는 장점이 있다고 한다. 

 

KVO 장단점

Advantages of using Key-Value Observing

- Multiple observers - there is no limitation on the number of subscribers. 다중 옵저버. 구독자 수에 제한이 없다

- no need to change the source code of the class under observation. 관찰 중인 클래스의 소스 코드를 변경할 필요가 없다. 

(외부라이브러리 사용할 때 KVO가 유리하다면 관찰할 클래스가 NSObject로 만들어져있고 업데이트 코드가 사전에 다 구현이 되어 있는 상황에서만 가능한거 아닌가..?)

- very low coupling 매우 낮은 결합도. - the observed party doesn’t even know it’s being observed, the observing party’s knowledge is bounded by the name of the @property

- 관찰된 값의 가장 최근 값 뿐만 아니라 이전 값도 전달하도록 Notification을 구성할 수 있다. 

Disadvantages of using Key-Value Observing

- One of the worst APIs across Cocoa.

- Each observer has to explicitly unsubscribe on deinit - otherwise crash is unavoidable. 각 옵저버는 명시적으로 구독을 취소해야 한다. 그렇지 않으면 충돌이 불가피.

- Relatively slow performance. 상대적으로 느린 성능. 

 

이러면 굳이 쓸 이유가..? 의문.. ㅋㅋ

 

 


참고 : 

https://developer.apple.com/documentation/swift/using-key-value-observing-in-swift

https://zeddios.tistory.com/1220

https://topic.alibabacloud.com/a/delegate-notificationkvo-pros-and-cons_8_8_31286426.html

https://nalexn.github.io/kvo-guide-for-key-value-observing/

https://nalexn.github.io/callbacks-part-1-delegation-notificationcenter-kvo/

 

728x90
반응형