개발콩블로그
[Swift] 프로퍼티 옵저버 (Property Observer) 본문
안녕하세요!
개발콩입니다. 오늘은 프로퍼티 옵저버(Property Observer)에 대해서 알아보도록 하겠습니다!!
프로퍼티 옵저버 (Property Observer)
- 프로퍼티의 값의 변화를 관찰하고 프로퍼티 값의 변화에 대응합니다.
- 프로퍼티의 현재 값과 같은 값을 저장해도 호출됩니다.
Apple에서 제공하는 예시코드를 한번 볼까요?
var totalSteps: Int = 200 {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
위의 코드에서 프로퍼티 옵저버는 저장 프로퍼티에서 사용되고 있습니다.
해당 프로퍼티의 값을 변경했을 때
willSet구문에서 지정한 pinrt문이 먼저 호출이 되고, 이후 didSet구문이 호출되는 것을 볼 수 있습니다.
willSet
- 값이 저장되기 직전에 호출됩니다.
- 파라미터의 이름을 지정하지 않았다면, newValue를 통해 사용할 수 있습니다.
didSet
- 새로운 값이 저장된 직후에 호출됩니다.
- 파라미터의 이름을 지정하지 않았다면, oldValue를 통해 사용할 수 있습니다.
프로퍼티 옵저버를 사용할 수 있는 공간
- 저장 프로퍼티
- 상속받은 저장 프로퍼티
- 상속받은 연산 프로퍼티
저장 프로퍼티와 상속받은 저장 프로퍼티의 경우 위의 예시코드와 비슷하여 이해하기 쉬웠습니다.
하지만, 프로퍼티 옵저버를 상속받은 연산 프로퍼티에도 적용할 수 있다는 것은 놓치지 쉬운 사실인 것 같습니다.
상속받은 연산 프로퍼티에서의 프로퍼티 옵저버
상속받은 연산 프로퍼티에서도 프로퍼티 옵저버를 활용할 수 있습니다.
class Plant {
var name: String = "flower"
var nameDescription: String {
get {
print("get")
return name
} set {
print("set - \(newValue)")
name = newValue
}
}
}
class Bean: Plant {
override var nameDescription: String {
willSet {
print("willSet - \(newValue)")
} didSet {
print("didSet - \(oldValue)")
}
}
}
let bean = Bean()
bean.nameDescription = "bean"
// get
// willSet - bean
// set - bean
// didSet - flower
저는 지금 bean.nameDescription에 값을 쓰고 있는 상황입니다.
get - willSet - set - didSet 순서로 잘 진행되는 것을 확인할 수 있습니다.
위의 코드에서는 didSet 구문에서 nameDescription을 변경하게 된다면,
무한 재귀가 발생하게 됩니다.
get - willSet - set - didSet -> get - willSet...
당연한 결과입니다.
그렇다면, 저장 프로퍼티에서의 무한재귀는 발생할까요?
프로퍼티 옵저버의 무한재귀
var counter: Int = 0 {
didSet {
counter += 1
print(counter)
}
}
counter = 0
// 1
다른 외국 블로그에는 아래의 코드를 무한재귀가 발생하는 코드로 소개하고 있습니다.
실제로 그려보면, 저장된 이후 -> 다시 값을 저장 (값 변경됨) -> 다시 + 1 -> 저장된 이후 ....
하지만 실제로 무한재귀가 발생하지 않습니다.
하지만 왜 didSet만 사용할 때는 무한재귀가 발생하지 않을까요?
해당 자료에 대해서 많은 자료를 찾아보았고, Apple 개발자 포럼에서 힌트를 얻을 수 있었습니다.
https://forums.developer.apple.com/forums/thread/105784
👉 Swift 5.0이 되면서 willSet, didSet에서 본인을 수정하는 것은 트리거 되지 않는다.
제 결론 및 느낀점
프로퍼티 옵저버는 저장 프로퍼티에서만 사용할 수 있을 것 같다는 편견을 없앨 수 있었던 것 같습니다.
연산 프로퍼티에서는 무한 재귀가 발생할 수 있어서 사용을 조심해야하지만,
프로퍼티 옵저버의 경우 생각과는 다르게 무한 재귀가 발생하지 않음을 알 수 있었습니다.
프로퍼티 옵저버를 공부하게 되면서 특정한 동작이 반복이 되는데,
이러한 동작의 시작이 프로퍼티의 값의 변경일 경우에 프로퍼티 옵저버를 잘 활용할 수 있을 것 같습니다.
참고
'swift' 카테고리의 다른 글
[Swift] GCD - 1 동시성 프로그래밍 (3) | 2025.01.25 |
---|---|
[Swift] 싱글톤 패턴 (Singleton Pattern) (0) | 2025.01.15 |
[Swift] 연산 프로퍼티(Computed Property) (2) | 2025.01.09 |
[Swift] Generic (1) | 2025.01.05 |
[Swift] Property Wrapper (0) | 2025.01.03 |