10-2. 프로퍼티 관찰자(property observer), 프로퍼티 래퍼
14356 단어 Swift Docs@property@property
프로퍼티 관찰자는 프로퍼티 값이 변경되는지 관찰하고 응답한다. 이는 현재 값이 새로운 값과 같아도 값이 설정되는 시기에 호출된다. 다음의 경우에 관찰자 추가가 가능하다.
- 정의한 저장된 프로퍼티
- 상속 저장된 프로퍼티
- 상속 계산된 프로퍼티
프로퍼티 관찰자
- 프로퍼티 관찰자 정의는 2가지 선택사항이 있으며, willSet과 didSet이 있다.
- willSet은 값이 저장되기 직전에 호출된다. 상수 파라미터로 새로운 프로퍼티 값이 전달된다. willSet 구현의 일부로 이 파라미터에 새로운 이름을 가질 수 있다. 파라미터명과 구현 시 소괄호를 작성하지 않으면 newValue의 기본 파라미터로 만들어진다
- didSet은 값이 저장되자마자 호출된다. 예전 프로퍼티값을 포함한 상수 파라미터가 전달된다. 파라미터명을 사용하거나 oldValue인 기본파라미터 사용이 가능하다. didSet관찰자 프로퍼티 값을 할당하게 되면 새로운 값으로 방금 설정한 값을 대체한다.
- 수퍼클래스 프로퍼티의 will, didSet 관찰자는 수퍼클래스 초기화가 호출된 후 하위클래스에서 프로퍼티가 설정될 때 호출된다. 수퍼클래스 초기화가 호출되기 전 클래스 자체 프로퍼티를 설정하는 동안 호출되지 않는다.
class StepCounter {
var totalStep : Int = 0 {
willSet(newTotalSteps) {
print("\(newTotalSteps)")
} didSet {
if totalSteps > oldValue {
print("\(totalSteps - oldValue)")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
//윌셋에서 200 출력, 디드셋에서 200(200-0)출력한다.
stepCounter.totalSteps = 360
//윌셋에서 360, 디드셋에서 160(360-200)을 출력한다.
//바뀌기 직전과 직후를 출력하므로 둘다 출력이 되고, 꼭 둘다 쌍으로 선언할 필요는 없다.
//oldValue를 통해서 디드셋에서 바뀌기 전 값 접근이 가능하다는게 포인트다.
- 관찰자를 가진 프로퍼티를 in-out파라미터로 함수에 전달하면 관찰자는 항상 호출이 된다. 함수에서 변경되는 변수의 상태를 실시간으로 파악하며 관찰 기능이 가능하다는 것이다.
프로퍼티 래퍼
- 프로퍼티 래퍼는 프로퍼티가 저장되는 방법을 관리하는 코드와 프로퍼티를 정의하는 코드사이에 분리계층을 추가한다. 프로퍼티 래퍼를 정의하기 위해서 wrappedValue 프로퍼티를 정의한 구조체, 열거형 또는 클래스를 만든다.
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue : Int {
get {
return number
}
set {
number = min(newValue, 12)
}
}
//게터는 저장된 값을 반환하고, 세터는 새로운 값이 12보다 작거나 같은걸 확인하고 반환한다.
//프로퍼티 래퍼는 wrappedValue를 프로퍼티의 값으로 반환해주게 된다.
- 다음 예시는 프로퍼티 래퍼를 활용한 예시를 들고 있다. 프로퍼티 래퍼는 프로퍼티에게 일정한 특성을 부여하는 키워드라고 생각하면 좋다.
struct SmallRectangle {
@TwelveOrLess var height : Int
@TwelveOrLess var width : Int
}
var rectangle = SmallRectangle()
print(rectangle.height)
//0을 출력한다.
rectangle.height = 10
//새로운 값을 넣어줬으니 setter가 작용할 것이다.
print(rectangle.height)
//아직 12보다 작으므로 10을 출력한다.
rectangle.height = 24
//세터가 작용하고 12보다 크므로 12를 출력한다.
- 래핑된 프로퍼티를 위한 초기값 설정은 프로퍼티 래퍼를 직접 초기화 해주어야 설정이 가능하다.
@propertyWrapper
struct SmallNumber {
private var maximum : Int
private var number : Int
var wrappedValue : Int {
get { return number }
set { number = min(newValue, maximun) }
//여기에서 보면 현재 구조체 내 프로퍼티에 값이 하나도 정의되지 않은 상태이다.
init() {
maximum = 12
number = 0
init(wrappedValue : Int) {
maximun = 12
number = min(wrappedValue, maximun)
}
init(wrappedValue : Int, maximum : Int) {
self.maximum = maximum
number = min(wrappedValue, maximun)
}
//기본적으로 3개의 초기화를 지원한다.
- 프로퍼티 래퍼에 대한 초기화 유형에 따라서 초기화 방식이 다 다르다. 다음에서 확인가능하다.
struct ZeroRectangle {
@SmallNumber var height : Int
@SmallNumber var width : Int
}
var zeroRectangle = ZeroRectangle()
print(zeroRectangle.height, zeroRectangle.width)
//0, 0을 출력한다. 가장 첫 init() 이 호출되기 때문이다.
struct UnitRectangle {
@SmallNumber var height : Int = 1
@SmallNumber var width : Int = 1
}
var unitRectangle = UnitRectngle()
print(unitRectangle.height, unitRectangle.width)
//1, 1을 출력한다. 초기값을 설정해줘도 init()을 호출한다.
//초기값으로 wrappedValue를 전달하지 않았기에 그렇다.
struct NarrowRectangle {
@SmallNumber(wrappedValue : 2, maximun : 5) var height : Int
@SmallNumber(wrappedValue : 3, maximun : 4) var width : Int
}
var narrowRectangle = NarrowRectangle()
print(narrowRectangle.height, narrowRectangle.width)
//2, 3을 출력한다. 다음에서는 래핑한 값을 통해서 초기화가 가능하다.
//위의 예시에서 3번에 해당하는 초기화를 사용하게 된다.
//init(wrappedValue : Int, maximun : Int)
Author And Source
이 문제에 관하여(10-2. 프로퍼티 관찰자(property observer), 프로퍼티 래퍼), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@devleeky16498/10-2.-프로퍼티-관찰자property-observer-프로퍼티-래퍼
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
class StepCounter {
var totalStep : Int = 0 {
willSet(newTotalSteps) {
print("\(newTotalSteps)")
} didSet {
if totalSteps > oldValue {
print("\(totalSteps - oldValue)")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
//윌셋에서 200 출력, 디드셋에서 200(200-0)출력한다.
stepCounter.totalSteps = 360
//윌셋에서 360, 디드셋에서 160(360-200)을 출력한다.
//바뀌기 직전과 직후를 출력하므로 둘다 출력이 되고, 꼭 둘다 쌍으로 선언할 필요는 없다.
//oldValue를 통해서 디드셋에서 바뀌기 전 값 접근이 가능하다는게 포인트다.
- 프로퍼티 래퍼는 프로퍼티가 저장되는 방법을 관리하는 코드와 프로퍼티를 정의하는 코드사이에 분리계층을 추가한다. 프로퍼티 래퍼를 정의하기 위해서 wrappedValue 프로퍼티를 정의한 구조체, 열거형 또는 클래스를 만든다.
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue : Int {
get {
return number
}
set {
number = min(newValue, 12)
}
}
//게터는 저장된 값을 반환하고, 세터는 새로운 값이 12보다 작거나 같은걸 확인하고 반환한다.
//프로퍼티 래퍼는 wrappedValue를 프로퍼티의 값으로 반환해주게 된다.
- 다음 예시는 프로퍼티 래퍼를 활용한 예시를 들고 있다. 프로퍼티 래퍼는 프로퍼티에게 일정한 특성을 부여하는 키워드라고 생각하면 좋다.
struct SmallRectangle {
@TwelveOrLess var height : Int
@TwelveOrLess var width : Int
}
var rectangle = SmallRectangle()
print(rectangle.height)
//0을 출력한다.
rectangle.height = 10
//새로운 값을 넣어줬으니 setter가 작용할 것이다.
print(rectangle.height)
//아직 12보다 작으므로 10을 출력한다.
rectangle.height = 24
//세터가 작용하고 12보다 크므로 12를 출력한다.
- 래핑된 프로퍼티를 위한 초기값 설정은 프로퍼티 래퍼를 직접 초기화 해주어야 설정이 가능하다.
@propertyWrapper
struct SmallNumber {
private var maximum : Int
private var number : Int
var wrappedValue : Int {
get { return number }
set { number = min(newValue, maximun) }
//여기에서 보면 현재 구조체 내 프로퍼티에 값이 하나도 정의되지 않은 상태이다.
init() {
maximum = 12
number = 0
init(wrappedValue : Int) {
maximun = 12
number = min(wrappedValue, maximun)
}
init(wrappedValue : Int, maximum : Int) {
self.maximum = maximum
number = min(wrappedValue, maximun)
}
//기본적으로 3개의 초기화를 지원한다.
- 프로퍼티 래퍼에 대한 초기화 유형에 따라서 초기화 방식이 다 다르다. 다음에서 확인가능하다.
struct ZeroRectangle {
@SmallNumber var height : Int
@SmallNumber var width : Int
}
var zeroRectangle = ZeroRectangle()
print(zeroRectangle.height, zeroRectangle.width)
//0, 0을 출력한다. 가장 첫 init() 이 호출되기 때문이다.
struct UnitRectangle {
@SmallNumber var height : Int = 1
@SmallNumber var width : Int = 1
}
var unitRectangle = UnitRectngle()
print(unitRectangle.height, unitRectangle.width)
//1, 1을 출력한다. 초기값을 설정해줘도 init()을 호출한다.
//초기값으로 wrappedValue를 전달하지 않았기에 그렇다.
struct NarrowRectangle {
@SmallNumber(wrappedValue : 2, maximun : 5) var height : Int
@SmallNumber(wrappedValue : 3, maximun : 4) var width : Int
}
var narrowRectangle = NarrowRectangle()
print(narrowRectangle.height, narrowRectangle.width)
//2, 3을 출력한다. 다음에서는 래핑한 값을 통해서 초기화가 가능하다.
//위의 예시에서 3번에 해당하는 초기화를 사용하게 된다.
//init(wrappedValue : Int, maximun : Int)
Author And Source
이 문제에 관하여(10-2. 프로퍼티 관찰자(property observer), 프로퍼티 래퍼), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@devleeky16498/10-2.-프로퍼티-관찰자property-observer-프로퍼티-래퍼저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)