봄날은 갔다. 이제 그 정신으로 공부하자

set, get, willSet, didSet 본문

iOS Tip

set, get, willSet, didSet

길재의 그 정신으로 공부하자 2022. 4. 13. 22:22

스위프트는 프로퍼티에 set, get, willSet, didSet 을 사용할 수 있습니다.

set, get이 세트이고 willSet, didSet이 세트 입니다.

하나의 프로퍼티에 4개를 모두 사용할 수는 없습니다.

set & get 그리고 willSet & didSet은 비슷해 보이지만 다른 사용성을 가집니다.

 

우선 set, get부터

set, get은 연산 프로퍼티(Computed Property)로 일반적인 프로퍼티(저장 프로퍼티)와 달리 저장 공간을 갖지 않고 다른 일반 프로퍼티의 값을 읽어 연산하거나 프로퍼티로부터 전달 받은 값을 다른 프로퍼티에 저장하는 역할을 하는 프로퍼티로 class, stuct, enum에서 사용가능한 프로퍼티 입니다.

연산 프로퍼티는 값을 저장하지 않기 때문에 타입 추론을 통해 형식을 알 수 없어 선언 시 반드시 자료형을 명시해야 하며

값을 set & get 하는 부분에 아래와 같이 get, set 키워드를 추가해주어야 합니다.

var name: Type {
    get {           //getter
        statements
        return expr
    }
    set(name) {     //setter
        statements
    }
}

 

set과 get을 사용해 최대 값이 100 이상 입력 되면 100으로 고정되는 프로퍼티를 만들 수 있습니다.

코드는 아래와 같습니다.

class MyComProperty {
    private var _myValue = 0
    var myValue: Int {
        set(value){
            _myValue = value > 100 ? 100 : value
        } get {
            return _myValue
        }
    }
}

var myComProperty = MyComProperty()
myComProperty.myValue = 100
print("myValue: \(myComProperty.myValue)")
myComProperty.myValue = 200
print("myValue: \(myComProperty.myValue)")

 

myValue의 set 연산자에서 입반 프로퍼티에 값을 저장하기 전에 100보다 큰 경우 무조건 100으로 저장되도록 처리하였기 때문에  출력 결과는 아래와 같습니다.

myValue: 100
myValue: 100

 

set 없이 get만 사용할 경우, 아래와같이 set 키워드를 생략하고 사용할 수 있습니다.

class MyComProperty {
    private var _myValue = 0
    var myValue: Int {
            return _myValue
    }
}

 

다음으로 willSet, didSet

set과 get이 일반 프로퍼티 값의 검증 또는 관리를 위해 사용되었다면 willSet과 didSet은 Observer로서 사용됩니다.

willSet은 값이 변경되기 직전에 호출되고 didSet은 값이 변경된 후 호출되며 반드시 값이 초기화 되어 있어야 합니다.

var addValue: Int = 0 {
   willSet(newValue) { 
        print("addValue: \(addValue) -> \(newValue)")
    }
    didSet(oldValue) {
        print("addValue: \(oldValue) -> \(addValue)")
    }
}

 

willSet과 didSet의 적절한 사용 방법은 한개의 값이 변경 될 때 따라서 자동으로 변경되어야 하는 값이 있다면 willSet과 didSet을 사용해주면 됩니다.

addValue 프로퍼티의 값을 변경 할 때 myValue의 값이 자동으로 변경되는 코드는 아래와 같습니다.

class MyComProperty {
    private var _myValue = 0
    var myValue: Int {
        set(value){
            _myValue = value > 100 ? 100 : value
        } get {
            return _myValue
        }
    }

    var addValue: Int = 0 {
        willSet(newValue) {
            print("willSet: \(myValue) -> \(newValue)")
            myValue += newValue
       }
    }
}


var myComProperty = MyComProperty()
myComProperty.myValue = 50
print("myValue: \(myComProperty.myValue)")
myComProperty.addValue = 10
print("addValue: \(myComProperty.addValue)")
print("myValue: \(myComProperty.myValue)")

 

아래 출력 결과로 알 수 있듯이 addValue 값만 변경했을 뿐인데 myValue도 같이 변경되어 있음을 알 수 있습니다.

myValue: 50
addValue: 10
myValue: 60

 

정리

set  & get: 값을 저장하지 않는 연산 프로퍼티로 일반 프로퍼티 값의 검증 및 관리를 위해 사용

willSet & didSet: 프로퍼티 변경 시 자동으로 변경되어야 하는 값이 있다면 willSet or didSet을 옵저버로 활용해 관리해주면 좋음.

 

Comments