https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties/
1. PropertyWrapper란?
파이썬의 데코레이션과 비슷하다. 파이썬의 데코레이션은 코드 앞뒤로 어떠한 코드를 붙여주는 작업을 해준다.
프로퍼티 래퍼또한 비슷하다. 어떤 프로퍼티 앞뒤로 특정한 작업을 넣을 수 있다.
2. 만드는법
만드는 방법은 간단하다.
1. struct를 정의할 때 @PropertyWrapper라고 적어준다
2. struct안에 wrappedValue라는 computedProperty를 정의해주면 된다
아래는 범위가 12까지인 프로퍼티를 프로퍼티 래퍼를 이용해 구현하는 예제이다
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
}
3. 사용법
프로퍼티 래퍼를 사용할 프로퍼티 앞에 @을 이용하여 연결해준다
아래의 코드에서 height와 width는 프로퍼티 래퍼의 wrappedValue와 연결된다고 생각하면 된다
struct SmallRectangle {
@TwelveOrLess var height: Int
@TwelveOrLess var width: Int
}
var rectangle = SmallRectangle()
print(rectangle.height)
// Prints "0"
rectangle.height = 10
print(rectangle.height)
// Prints "10"
rectangle.height = 24
print(rectangle.height)
// Prints "12"
실제로 위 코드는 컴파일러에 의해서 아래와 같이 번역된다
struct SmallRectangle {
private var _height = TwelveOrLess()
private var _width = TwelveOrLess()
var height: Int {
get { return _height.wrappedValue }
set { _height.wrappedValue = newValue }
}
var width: Int {
get { return _width.wrappedValue }
set { _width.wrappedValue = newValue }
}
}
4. 프로퍼티 래퍼의 초기값 설정
위 예제에서는 바로 0을 넣어서 초기값을 설정해 주었지만 실제로는 아래처럼 init을 이용하여 다양한 방법으로 초기화가 가능하다
@propertyWrapper
struct SmallNumber {
private var maximum: Int
private var number: Int
var wrappedValue: Int {
get { return number }
set { number = min(newValue, maximum) }
}
init() {
maximum = 12
number = 0
}
init(wrappedValue: Int) {
maximum = 12
number = min(wrappedValue, maximum)
}
init(wrappedValue: Int, maximum: Int) {
self.maximum = maximum
number = min(wrappedValue, maximum)
}
}
아래처럼 사용하면 첫번째 init()을 사용하게 된다
struct ZeroRectangle {
@SmallNumber var height: Int
@SmallNumber var width: Int
}
var zeroRectangle = ZeroRectangle()
print(zeroRectangle.height, zeroRectangle.width)
// Prints "0 0"
아래 내용은 init(wrappedValue:)을 사용하는 예제이다.
기본적으로 PropertyWrapper을 사용한 변수에 assign( = 을이용하여 값 부여) 하면 initializer에 wrappedValue에 맵핑된다!
struct UnitRectangle {
@SmallNumber var height: Int = 1
@SmallNumber var width: Int = 1
}
var unitRectangle = UnitRectangle()
print(unitRectangle.height, unitRectangle.width)
// Prints "1 1"
다음으로는 init(wrappedValue:, maximum:)을 사용하는 예제이다
struct NarrowRectangle {
@SmallNumber(wrappedValue: 2, maximum: 5) var height: Int
@SmallNumber(wrappedValue: 3, maximum: 4) var width: Int
}
var narrowRectangle = NarrowRectangle()
print(narrowRectangle.height, narrowRectangle.width)
// Prints "2 3"
narrowRectangle.height = 100
narrowRectangle.width = 100
print(narrowRectangle.height, narrowRectangle.width)
// Prints "5 4"
앞서 말한것처럼 = 을 이용하면 wrappedValue에 맵핑된다고 했다. 이를 이용하면 아래처럼도 사용 가능하다
struct MixedRectangle {
@SmallNumber var height: Int = 1
@SmallNumber(maximum: 9) var width: Int = 2
}
var mixedRectangle = MixedRectangle()
print(mixedRectangle.height)
// Prints "1"
mixedRectangle.height = 20
print(mixedRectangle.height)
// Prints "12"
5. ProjectedValue
프로퍼티 래퍼에는 또하나의 기능이 있다. wrappedValue를 다른값으로 Projecting 할 수 있는 기능이다.
가령 내가 어떤 시간을 int로 표현하면, 이를 년도 월 일 형식으로 바꿔서 표현해줄 수 있는 기능이라고 해야하나
아래는 공식문서에서 나온 내용이다. 방법은 간단하다 projectedValue를 정의해주면 된다
아래 코드 설명은 간단하다. 값을 할당하는데 12가 넘으면 true, 아니면 false로 프로젝팅 하고있다.
즉 값이 깍여서 들어왔냐 아니냐를 projectedValue로 표현한 것이다.
유용한 기능인지는 잘 모르겠다.
@propertyWrapper
struct SmallNumber {
private var number: Int
private(set) var projectedValue: Bool
var wrappedValue: Int {
get { return number }
set {
if newValue > 12 {
number = 12
projectedValue = true
} else {
number = newValue
projectedValue = false
}
}
}
init() {
self.number = 0
self.projectedValue = false
}
}
struct SomeStructure {
@SmallNumber var someNumber: Int
}
var someStructure = SomeStructure()
someStructure.someNumber = 4
print(someStructure.$someNumber)
// Prints "false"
someStructure.someNumber = 55
print(someStructure.$someNumber)
// Prints "true"
'iOS > Swift배우기' 카테고리의 다른 글
Xcode에서 SwiftUI 코드선택 익숙해지기 (0) | 2024.03.22 |
---|---|
[SwiftUI] 자식에게 State 전달하기 (0) | 2024.03.21 |
SwiftUI에서 {} 동작 원리 (0) | 2024.03.20 |
[Swift] Generic이란 (0) | 2024.03.20 |
[Swift] inout 파라미터 (0) | 2024.03.20 |
댓글