8.2.3 프로퍼티 옵저버
프로퍼티 옵저버(Property Observer)는 특정 프로퍼티를 계속 관찰하고 있다가 프로퍼티의 값이 변경되면 이를 알아차리고 반응합니다. 프로퍼티의 값이 설정되면 무조건 호출되며, 동일한 값이 재할당되더라도 호출됩니다. 프로퍼티 옵저버에는 willSet과 didSet 두 종류가 있습니다.
willSet - 프로퍼티 값이 변경되기 직전에 호출되는 옵저버
didSet - 프로퍼티의 값이 변경된 직후에 호출되는 옵저버
willSet 옵저버를 구현해 둔 프로퍼티에 값을 대입하면 그 값이 프로퍼티에 대입되기 직전에 willSet 옵저버가 실행됩니다. 이때 프로퍼티에 대입되는 값이 옵저버의 실행 블록에 매개상수 형식으로 함께 전달됩니다. 프로퍼티의 값이 변경되기 전에 처리해야 할 뭔가가 있다면 이 값을 이용하여 처리하면 됩니다. 단 전달된 값은 참조할 수는 있지만, 수정할 수는 없습니다. 어쨌거나 상수 형태로 전달하는 값이니까요. 매개상수에 이름을 부여해도 하지 않아도 되는데, 부여하지 않을 때는 매개상수 이름과 괄호를 모두 생략하면 됩니다. 생략한 경우에는 기본 상수명인 newValue라는 이름으로 전달되므로 이 상수를 사용해서 필요한 작업을 처리할 수 있습니다.
var <프로퍼티명> : <타입> [ = <초기값> ] {
willSet [ (<인자명>) ] {
<프로퍼티 값이 변경되기 전에 실행할 내용>
}
}
문법 형식에서 대괄호 []에 둘러싸여 표시되는 부분은 생략이 가능한 부분입니다. 실제 구문을 작성할 때는 대괄호를 표시하지 않습니다.
didSet의 경우는 프로퍼티에 값이 대입된 후 호출됩니다. 새로 할당된 값이 아닌 이전에 저장되어 있던 값이 매개상수 형태로 전달됩니다. 그 매개상수에 이름을 부여할 수 있지만 생략하더라도 oldValue라는 이름으로 자동 전달됩니다.
var <프로퍼티명> : <타입> [ = <초기값> ] {
didSet [ (<인자명>) ] {
<프로퍼티 값이 변경된 후에 실행할 내용>
}
}
willSet, didSet을 함께 구현해야 하는 것은 아닙니다. 한쪽 옵저버만 필요한 경우에는 나머지 하나는 구현할 필요 없이 선택적으로 구현하면 됩니다.
struct Job {
var income: Int = 0 {
willSet(newIncome) {
print("이번 달 월급은 \(newIncome)원입니다")
}
didSet {
if income > oldValue {
print("월급이 \(income - oldValue)원 증가하셨네요. 소득세가 상향조정될 예정입니다")
} else {
print("저런, 월급이 삭감되셨군요. 그래도 소득세는 깎아드리지 않아요. 알죠?")
}
}
}
}
직장인의 월급을 매의 눈으로 주시하고 있다가 월급이 오르기 무섭게 추가된 소득세를 챙겨가는 국세청을 프로퍼티 옵저버로 표현한 예제입니다.
willSet 구문에서 newIncome으로 인자를 받아 income에 대입됩니다. didSet구문에는 파라미터가 없는데, 기본 파라미터인 oldValue를 사용하여 새로 대입된 income과 oldValue의 값을 비교하여 문장을 출력합니다.
월급의 초기값을 백만 원으로 입력해서 Job 인스턴스를 생성하겠습니다.
var job = Job(income: 1000000)
월급이 백만 원인 Job 인스턴스가 생성되어 job 변수에 할당되었습니다. 상수가 아닌 변수에 할당한 것은 조금 후 income 프로퍼티의 속성을 변경하기 위해서입니다. 월급을 올려보겠습니다.
job.income = 2000000
// 실행 결과
이번 달 월급은 2000000원입니다
월급이 1000000원 증가하셨네요. 소득세가 상향조정될 예정입니다
실행 결과를 보시면 willSet 구문이 먼저 실행되고 프로퍼티의 값이 변경된 뒤 didSet 구문이 실행된 것을 알 수 있습니다.
이번엔 월급을 삭감해 봅시다.
job.income = 1500000
// 실행 결과
이번 달 월급은 1500000원입니다
저런, 월급이 삭감되었군요. 그래도 소득세는 깎아드리지 않아요. 알죠?
동일하게 willSet -> 프로퍼티 값 변경 -> didSet 임을 알 수 있습니다.
Last updated