Published 2022. 10. 6. 17:20

KVO란, 

Objectproperties의 변경다른 Object에 알리기 위한 Cocoa programming pattern

NSObject를 상속한 Object에서만 KVO 사용가능하다.

또한, NSObject에 KVO를 위한 기본적인 methods가 잘 구현되어 있기 때문에 Override 할 필요가 없다.

 

 

KVO in Swift

우선, KVO를 사용하기 위해 NSObject를 상속 하여야 한다. 

또한, Obeserve(관찰)할 property에 대해

@objc attribute와 dynamic modifier를 추가한다.

 

class Address: NSObject {
    @objc dynamic var cityName: String
    
    init(cityName: String) {
        ...
    }

}

class Person: NSObject {
    var name: String
    @objc dynamic var address: Address
    var myObserver: NSKeyValueObservation?
    
    init(name: String, address: Address) {
        ...
    }
}

우선 Person class내부의 address의 cityName property의 변화를 Observe할 것이기 때문에 

address와 Address클래스 내부의 cityName에 

@objc attribute와 dynamic modifier를 추가한다.

dynamic modifierObjective-C runtime 방식을 사용하겠다는 것이다.

 

이제 Observe를 구현해보자

observe를 생성 할때 

observe(_:options,:changeHandler:) 를 통해 생성한다. 

class Person: NSObject {
    var name: String
    @objc dynamic var address: Address
    var myObserver: NSKeyValueObservation?
    init(name: String, address: Address) {
        self.name = name
        self.address = address
        
        super.init()
        self.myObserver = observe(\.address.cityName,
                                   options: [.old, .new]) { object, change in
            print("\(change.oldValue)에서 \(change.newValue)로 바뀌었습니다.")
        }
    }
}

 

keyPath를 통해 지정한 위치의 property의 변화를 Observe(관찰)하게 된다. 

changeHandler에서 변한 값을 handler할 수 있다. 

let address = Address(cityName: "seoul")
let person = Person(name: "Jung", address: address)

let referenceWritableKeypath = \Person.address.cityName

person[keyPath: referenceWritableKeypath] = "busan"
//Optional("seoul")에서 Optional("busan")로 바뀌었습니다.

 

options는 생략이 가능한대, 변경이 필요 없을때, 생략하면 된다.

self.myObserver = observe(\.address.cityName) { object, change in
    print("\(change.oldValue)에서 \(change.newValue)로 바뀌었습니다.")
}

이렇게 생략하게 되면 

 

let address = Address(cityName: "seoul")
let person = Person(name: "Jung", address: address)

let referenceWritableKeypath = \Person.address.cityName

person[keyPath: referenceWritableKeypath] = "busan"
//nil에서 nil로 바뀌었습니다.

변화를 관찰 하지 않기 때문에 nil로 나오게 된다.

 

그외에도 options에는

  • new
  • old
  • initial
  • prior

4가지를 제공해준다. 

initial의 경우에는 초기화 시점부터 값의 변화를 알고 싶을 때 사용하고, 

prior은 이전의 상태까지 한번에 알고 싶은 경우에 사용한다.

 

 

장단점 

장점 

MVC pattern에서 controller는 view와 model의 변화를 관찰 해야 할때, 사용할 수 있다.

 

keyPath를 사용하여, 계층적인 객체의 프로퍼티도 쉽게 관찰 할 수 있다.

 

Controller의 경우 Model를 바라보게 됨. 또한, View는 Model의 관찰을 Controller를 통해서 함. 

 

단점

objective-c의 runtime에 의존적이게 된다.

Reference

 

'iOS > Swift' 카테고리의 다른 글

[Swift] KVO, Delegate and Notification  (2) 2022.10.08
[Swift] Notification  (0) 2022.10.08
[Swift] Delegate  (0) 2022.10.07
[Swift] KVC (Key-Value-Coding)  (1) 2022.10.05
[Swift] Subscript  (4) 2022.10.05
복사했습니다!