본문 바로가기

iOS/Swift

Swift) 프로퍼티 정복하기 (4/4) - 프로퍼티 옵저버(Property Observer)

 

 

 

안녕하세요!! 소들입니다 :)

오늘은 프로퍼티 정복하기 마지막 편 ~.~

사실 Property Wrapper라고, 좀 심화된 개념이 하나 더 있긴 한데,

이것을 쓸..ㅈ..ㅣ..말지..는.........ㄴ..ㅐ..맴........

 

쨌든 이번 포스팅에선

프로퍼티 옵저버라는 것에 대해 공부할 것이에요!!!

엄~~~~~~청 간단한 개념이니 한번 공부할 때 제대로 알아 둡시다 :)

모든 포스팅은 편의 말투로 합니다~!!

 

 

 

 

1. 프로퍼티 옵저버란(Property Observer)?

 

프로퍼티 값의 변화를 관찰하는 것으로, "저장 프로퍼티"에 추가할 수 있다

새 값의 속성이 현재 값과 동일하더라도 속성 값이 설정되면 호출된다

 

음..~~  여러분!! 옵저버가 뭐임??

"관찰자 👀" 라는 뜻을 가지지 않았음!?!?

 

따라서 프로퍼티 옵저버는, 말 그대로 프로퍼티를 관찰 👀하는 것

내가 관찰하는 프로퍼티에 누가 값을 설정하려고 한다!!!!???

 

그러면 이제

삐용삐용🚨프로퍼티 변경 감지 감지🚨삐용삐용

하면서, 이 프로퍼티 값 변경되려고 해! 하고 우리에게 알려주는 것이 바로

프로퍼티 옵저버라는 것임!!

 

근데, 이 프로퍼티 옵저버는 우리가 앞서 배운 

"저장 프로퍼티"에 한정되어 추가할 수 있음!!!

(연산 프로퍼티는 조건이 있는데, 좀이따 보겠음)


쨌든

이 프로퍼티 옵저버는 총 두 가지 옵션이 있는데

 

 willSet 

  값이 저장되기 직전에 호출된다

 didSet 

 새 값이 저장된 직후에 호출된다

 

사용법에 대해 알아보잣!!!!!

 

 

 

1-1. willSet

 

willSet 옵저버를 구현하면,

값이 저장되기 "직전"에 새로 저장될 값이 "파라미터"로 전달 된다

이때 파라미터 이름은 지정할 수 있지만,

파라미터 이름과 괄호를 따로 지정하지 않을 경우 newValue로 사용한다

 

 

var name: String = "Unknown" {
    willSet(newName) {
        print("현재 이름 = \(name), 바뀔 이름 = \(newName)")
    }
}
 

 

 

willSet 옵저버는 "저장 프로퍼티"에 위와 같이 구현함!!! 

newName이라는 파라미터 이름을 내가 지정해서 받아서 위처럼 사용할 수 있음!

 

근데,,,, 연산 프로퍼티 setter 구현할 때도 그랬지만,

파라미터 이름 설정하는 것이 개발자의 가장 큰 스트레스 잖음??

 

따라서 파라미터 부분을 싹 지우면, 기본적으로 정의되어 있는

"newValue" 라는 파라미터 이름으로 접근할 수 있음!!!!

 

 

var name: String = "Unknown" {
    willSet {
        print("현재 이름 = \(name), 바뀔 이름 = \(newValue)")
    }
}
 

 

 

요롷게!!! :) 간편데스네~

 

자, 프로퍼티 옵저버는 누군가 해당 프로퍼티에 값을 "설정"할 때 위잉하고 작동한다 했음!

따라서 다음과 같이 내가 name이란 저장 프로퍼티에 값을 쓰려고 하면,

 

 

name = "Sodeul"

 

 

그럼 이제 willSet이 호출되는 것임!! 근데 뭐라고~~?

willSet은 실제 name이란 프로퍼티의 값이 Sodeul로 변경되기 "직전"에 호출 되는 것임!!!

따라서 아직 name의 값은 Sodeul로 변경되기 전이기 때문에,

 

 

 

 

이런 우리가 willSet에 작성한 print가 호출되는 것임 :)

다시 말하지만 값이 변경되기 "직전"에 호출되는 것이라

현재 이름(name)은 아직 이전 값인 Unknown인 것임!!!!

 

이제 willSet에 대한 감이 왔을 것이라 믿고, didSet으로 갑시다 :)

 

 

 

1-2. didSet

 

didSet 옵저버를 구현하면,

값이 저장된 "직후"에 이전 프로퍼티의 값이 "파라미터"로 전달 된다

이때 파라미터 이름은 지정할 수 있지만,

파라미터 이름과 괄호를 따로 지정하지 않을 경우 oldValue로 사용한다

 

 

var name: String = "Unknown" {
   didSet(oldName) {
        print("현재 이름 = \(name), 바뀌기 전 이름 = \(oldName)")
    }
}
 

 

 

didSet 옵저버는 "저장 프로퍼티"에 위와 같이 구현함!!! 

oldName이라는 파라미터 이름을 내가 지정해서 받아서 위처럼 사용할 수 있음!

 

하지만 willSet과 마찬가지로

파라미터 부분을 싹 지우면, 기본적으로 정의되어 있는

"oldValue" 라는 파라미터 이름으로 접근할 수 있음!!!!

 

 

var name: String = "Unknown" {
   didSet {
        print("현재 이름 = \(name), 바뀌기 전 이름 = \(oldValue)")
    }
}
 

 

 

요롷게!!! :)

 

willSet과 마찬가지로 didSet도 프로퍼티 옵저버이기 때문에,

누군가 이 프로퍼티에 값을 "설정"할 때 위잉하고 작동한다 했음!

따라서 다음과 같이 내가 name이란 저장 프로퍼티에 값을 쓰려고 하면,

 

 

name = "Sodeul"

 

 

그럼 이제 didSet이 호출되는 것임!! 근데 뭐라고~~?

didSet은 실제 name이란 프로퍼티의 값이 Sodeul로 변경된 "직후"에 호출 되는 것임!!!

따라서 저장 프로퍼티인 name의 값은 Sodeul로 변경된 후기 때문에,

 

 

 

 

이런 우리가 didSet에 작성한 print가 호출되는 것!!!

값이 변경된 "직후"에 호출되는 것이라

현재 이름(name)은 변경된 값인 "Sodeul"이고,

이전에 저장되어 있던 Unknown이 파라미터 oldValue로 넘어온 것임!!!!

 

didSet도 어렵지 않을 것이라 믿고.. :)

 

 

 

1-3. 당연히 willSet & didSet을 같이 구현할 수 있다

 

 

var name: String = "Unknown" {
    willSet {
        print("현재 이름 = \(name), 바뀔 이름 = \(newValue)")
    }
    didSet {
        print("현재 이름 = \(name), 바뀌기 전 이름 = \(oldValue)")
    }
}
 
name = "Sodeul"
 

 

 

name이란 값을 변경하려고 하면,

 

 

 

 

① willSet이 먼저 실행되고

② 저장 프로퍼티 name의 값이 변경되고

③ didSet이 실행되고

 

 

이 순으로 둘다 실행 돼용🌝

 

 

 

 

2. 연산 프로퍼티도 프로퍼티 옵저버를 추가할 수 있다!?

 

위에서 프로퍼티 옵저버는 "저장 프로퍼티"에 한해

추가할 수 있다고 했는데,

 

사실 연산 프로퍼티도 프로퍼티 옵저버를  추가할 수 있음!!!

다만, 조건이 있음

 

부모 클래스의 연산 프로퍼티를 오버라이딩 할 경우

프로퍼티 옵저버를 추가할 수 있다

 

 

음 이게 무슨 말이냐면

 

 

class Human {
    var name = "Unknown"
    var alias: String {
        get {
            return name + " 바보"
        }
        set {
            name = newValue + "별명에서 붙여진 이름"
        }
        willSet { }       // error! 'willSet' cannot be provided together with a getter
        didSet  { }       // error! 'didSet' cannot be provided together with a getter
    }
}
 

 

 

원래 이렇게 일반 연산 프로퍼티인 alias엔 프로퍼티 옵저버를 추가가 안됨

willSet과 didSet을 getter와 함께 쓸 수 없다고 에러마저 뜸...!!

왜냐?? setter를 통해 값 변경을 감지할 수 있는데, 왜 굳이굳이 프로퍼티 옵저버를 만드느냐 이거임!!!

 

 

근데, 이 Human이라는 클래스를 상속받는 Sodeul이란 클래스를 만들고,

alias란 부모 클래스의 연산 프로퍼티를 "오버라이딩"하면,

 

 

class Sodeul: Human {
    override var alias: String {
        willSet {
            print("현재 alias = \(alias), 바뀔 alias = \(newValue)")
        }
        didSet {
            print("현재 alias = \(alias), 바뀌기 전 alias = \(oldValue)")
        }
    }
}
 

 

 

이 경우엔 위처럼 연산 프로퍼티에 프로퍼티 옵저버를 추가해서

사용할 수 있음 :)

 

실제로 alias란 연산 프로퍼티에 값을 설정하려고 하면,

 

 

let sodeulSodeul = .init()
sodeul.alias = "소들이"

 

 

alias에 설정된 프로퍼티 옵저버가 모두

 

 

 

 

잘 동작 함 :)

(예제 결과 진짜 멋없네 -.-;;)

 

 

 

 

 

 

 

 

.

.

.

 

자 이제 프로퍼티 정복하기 포스팅 끝!! :)

사실 이 4가지 포스팅만 제대로 알고 있어도

개발하는 데 큰 문제는 없을 거 같아요!!!!

 

심화 개념은 나중에 조금 더 부지런한 내가 포스팅 할 거라 믿고..!!!

혹시 헷갈리는 개념이나 이해 안 가는 부분,

잘못된 부분 피드백은 언제든 댓글 주세요!!!!!

 

나를 포함한 누군가에게 도움이 되었길 바라며 :)

20,000

 



Calendar
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
최근 댓글
Visits
Today
Yesterday