프로퍼티 값의 변화를 관찰하고 반응한다.
프로퍼티의 값이 변경될 때마다 Property Observer
가 실행된다. 바뀐 값이 기존 값과 똑같아도 상관없이 실행됨.
다음과 같은 경우에 사용할 수 있다.
상속받은 프로퍼티의 경우, 그 프로퍼티를 subclass에 재정의(overriding)함으로써 프로퍼티 옵저버를 추가할 수 있다.
내가 정의해둔 계산 프로퍼티의 경우에는 옵저버를 추가하는 것보다 setter를 사용해서 value의 변경을 확인하고 반응하면 됨!
Overriding에 대해서는 다음에 다시 다뤄보자. 상속 페이지에 있음!
옵저버를 추가하려면 다음 둘 중 하나 이상을 정의해주면 된다.
willSet
은 값이 저장되기 직전에 실행됨didSet
은 새로운 값이 저장된 직후에 실행됨willSet
옵저버를 구현하면, 새로운 값을 상수 매개변수로 전달해준다. 이름은 맘대로 정하면 되는데, 딱히 안 정하고 계산 프로퍼티의 setter처럼 newValue
라는 기본 이름으로 사용해도 된다.
didSet
옵저버를 구현할 면, 이전 값을 상수 매개변수로 전달해 준다. 이름은 똑같이 맘대로 정해도 되고 oldValue
라는 기본 이름을 사용할 수 있음!
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("\(totalSteps) to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// 0 to 200
// Added 200 steps
stepCounter.totalSteps = 360
// 200 to 360
// Added 160 steps
stepCounter.totalSteps = 896
// 360 to 896
// Added 536 steps
totalSteps
라는 Int
타입 저장 프로퍼티에다가 옵저버를 추가한 코드이다.
요 변수가 다른 값으로 바뀔 때마다 willSet, didSet이 실행됨!
처음 200으로 바꿨을 때, willSet에서 totalSteps는 그대로 0이다. 왜냐하면 willSet은 값이 바뀌기 직전에 실행되므로!
didSet에서는 값이 바뀐 직후에 실행되므로 totalSteps는 200으로 바뀐 상태고, 원래 값을 접근하려면 oldValue를 사용하면 됨.
기존 계산 프로퍼티에는 setter 가 있기 때문에 굳이 옵저버를 추가할 필요가 없다!
근데 요걸 부모 클래스를 상속받는 subClass에서 해당 프로퍼티를 오버라이딩하면 옵저버를 따로 추가할 수가 있음!
class NameString {
var name = "Unknown"
var alias: String {
get {
return name + " velog"
}
set {
name = newValue + " subscribe"
}
}
}
class MyName: NameString{
override var alias: String {
willSet {
print("\(alias) changed to \(newValue)")
}
didSet {
print("\(oldValue) changed to \(alias)
}
}
}
요런식으로 상속받아서 오버라이딩한 계산 프로퍼티에 옵저버를 추가할 수 있다.
상속과 오버라이딩에 관한 건 다음에!