IOS

[IOS] 프로퍼티 초기화(get, set, didset, willset)

hyukji 2022. 11. 28. 20:35

프로퍼티는 크게 Stored property(저장 프로퍼티), Computed property(연산 프로퍼티) 두 가지로 나누어 진다.

 

Stored property(저장 프로퍼티)

 : 상수와 변수값을 인스턴스의 일부로 저장한다. 즉 특정 값을 저장하는 역할을 맡고 있고 저장할 메모리 공간을 가지고 있다. 클래스 구조체 뿐만 아니라 열거형에도 추가 될 수 있다.

struct rectangle {
    let height: Int
    var width: Int
}

var _rectangle = rectangle(height: 3, width: 3)

_rectangle.height = 6 // let 상수이므로 에러
_rectangle.width = 3

 해당 코드에서 height, width 가 바로 저장 프로퍼티다!

 

 

Computed property(연산 프로퍼티)

 : 다른 프로퍼티의 값을 연산처리해 간접적으로 값을 제공한다. 다른 프로퍼티에서 저장된 값을 읽어 필요한 계산을 한 후에 반환(return)을 해준다. 따라서 접근할 때마다 값이 달라지기에 let이 아닌 var로만 선언이 가능하다. 또한 특정 값을 저장하고 있지 않아 메모리 공간을 가지지 않는다. 연산프로퍼티는 선언 시점에 기본값을 저장하지 않아 Type 선언을 해주어야 한다.

struct rectangle {
    let height: Int
    var width: Int
    
    var _color : Int
    var color : UIColor { 
    	get {
        	return _color
        }
        set {
        	_color = newValue
        }
    }
}

var _rectangle = rectangle(height: 3, width: 3)

print(_rectangle.color)
_rectangle.color = .green

위의 연산 프로퍼티 color에 사용된 getset을 살펴보자.

 

  • get : 연산 프로퍼티에서 다른 프로퍼티에서 값을 연산처리해 간접적으로 값을 제공할 때 사용된다. 해당 구문에서 return을 반드시 명시해 주어야 한다. 
  • set : 연산 프로퍼티에서 값을 할당 혹은 변경할 때 사용된다. 위의 예제처럼 괄호와 파라미터를 생략해도 된다. 단일 생략하였다면 파라미터는 newValue 키워드로 접근이 가능하다. set을 생략해 Read-olny Computed Property(읽기 전용 속성)으로 사용되지만 get은 생략이 불가능하다.

 

또한 연산 프로퍼티는 값을 저장하고 있지 않기 때문에 다른 저장 프로퍼티(저장소)가 필요하다. 따라서 위의 코드에서는 _color라는 저장 프로퍼티를 저장소로 사용했다. 만일 저장 프로퍼티를 만들지 않는다면 아래 코드와 같이 에러가 발생한다.

struct rectangle {
    let height: Int
    var width: Int
    
    var color : UIColor { 
    	get {
        	return color // 재귀에러
        }
        set {
        	color = newValue // 저장 공간이 존재하지 않아 에러
        }
    }
}

var _rectangle = rectangle(height: 3, width: 3)

print(_rectangle.color) 
_rectangle.color = .green

 

 

 

다음으로 Proverty Observer(프로퍼티 옵저버) 을 살펴보자!

 

Proverty Observer(프로퍼티 옵저버)

 : Proverty Observer(프로퍼티 옵저버)는 특정 프로버티를 계속 관찰하고 있다가 값이 변경 될때 호출된다. 설정되는 값에 상관 없기 때문에 동일한 값 재설정에도 호출된다. 프로퍼티 옵저버는 값의 변경 직전의 이벤트를 감지하는 willset, 변경 직후의 이벤트를 감지하는 didset 두 가지가 존재한다.

 

중요한 것은 프로퍼티 옵저버를 사용하기 위해서는 해당 프로퍼티를 반드시 초기화 시켜주어야 한다. 예제를 통해 살펴보자!

var stringNum : String = "0" {
    willSet{
        print("\(self.stringNum) will set to \(newValue)")
    }
    didSet{
        print("\(oldValue) set to \(self.stringNum)"
    }
}

 

willset은 아직 변경시키기 전이므로 기존의 값은 프로퍼티 안에있고 새로운 값은 newValue 키워드에 저장되어 있음을 확인할 수 있다. 반대로 didset은 변경시킨 후이기 때문에 예전값은 oldValue 키워드에 저장되어 있고 새로운 값은 프로퍼티 안에 저장되어 있다.

 

해당 코드를 실행 시켜 stringNum을 8에서 89로 바꾸어 보았다.

프로퍼티 옵저버 실행 결과