๊ฐ์
์ ๋๋ก ํ๋กํผํฐ ๋ํผ๋ฅผ ์ดํดํ์ง ๋ชปํ ์ฑ๋ก ์ด๋ค๊ฐ ์ค์ ๊ณต๋ถ ์ค ๋๋ฌด ๋ง์ ํ๋กํผํฐ ๋ํผ์ ๋ฑ์ฅ์ผ๋ก ํผ๋ฏธํด์ง ์ ์ ์ ๋ถ์ฌ์ก๊ณ ๋์์์ต๋๋ค…๐ซ ์ค์ ์ @Published, @Binding, @ObservedObject ์ด๋ฐ ์ ๋ค์ด ๋ค property wrapper๋ผ๊ณ ํ๋ค์.
You can also use a property wrapper to reuse code in the getter and setter of multiple properties.
์์ง๋ property wrapper๊ฐ ์ ํํ ๋ญ ์ํ๊ฑด์ง & ์ด๋ป๊ฒ ์ฌ์ฉํ๋๊ฑด์ง ์ ๊ฐ์ด ์์์ … ์ ํ ๊ณต์ ์ค์ํํธ ๋ฌธ์์๋ ์ด๋ ๊ฒ ์จ์ ธ์์ต๋๋ค.
์ฌ๋ฌ ํ๋กํผํฐ์ getter, setter์ ์๋ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๊ธฐ ์ํด์ property wrapper๋ฅผ ์ฌ์ฉํ๋ค! ๊ทธ๋ผ ๊ฒฐ๊ตญ property wrapper๋ getter, setter์ ์ญํ ์ ๋์์ ํด์ฃผ๊ณ ์๋๊ฑด๊ฐ ?! ๋์ถฉ ๊ทธ๋ ๊ฒ ๊ฐ์ ์ก์๋ด ๋๋ค … ๋ง๋์ง ๊ณต๋ถํ๋ฉด์ ์์๋ด ์๋ค ๐
๊ณต์ ๋ฌธ์์์ ์์๋ณด์
property wrapper๋ ํ๋กํผํฐ๋ฅผ ์ ์ฅํ๋ ์ฝ๋์ ์ ์ํ๋ ์ฝ๋ ์ฌ์ด์ ๊ณ์ธต์ ์ถ๊ฐํฉ๋๋ค. ๋ฌด์จ ์๋ฆฌ์ผ์ง.. ์กฐ๊ธ ๋ ์์๋ด ์๋ค.
์ ์
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue: Int {
get {
number
}
set {
// number์๋ ๋ฌด์กฐ๊ฑด 12๋ณด๋ค ๊ฐ๊ฑฐ๋ ์์ ๊ฐ์ด ๋ค์ด๊ฐ๊ฒ ๋จ
number = min(newValue, 12)
}
}
}
property wrapper๋ enum, class, struct๋ฅผ ๋ชจ๋ ์ฌ์ฉํด์ ์์ฑํ ์ ์์ต๋๋ค.
์ ์ํ ๋ @propertyWrapper๋ฅผ ๋ถ์ด๋ฉด ๋ง๋ค ์ ์์ด์!
๊ทธ๋ฆฌ๊ณ ํ์์ ์ผ๋ก wrappedValue๋ผ๋ ๋ณ์๋ฅผ ์ ์ธ ๋ฐ ๊ตฌํํด์ค์ผ ํฉ๋๋ค.
๊ทธ๋ฌ๋ฉด ์ ์ฅ ๋ฐ ๋ถ๋ฌ์ค๊ณ ์ ํ๋ ๋ณ์์ ์ ๊ทผํ ๋ ์ง์ ์ ๊ทผํ๋๊ฒ ์๋๋ผ wrappepdValue๋ฅผ ํตํด ์ ์ฅํ๊ฑฐ๋ ๊ฐ์ ๋ถ๋ฌ์ฌ ์ ์๊ฒ ๋๋๊ฑฐ์ฃ .
์ฌ์ฉ
struct Rectangle {
@TwelveOrLess var height: Int = 0
@TwelveOrLess var width: Int = 0
}
var testRectangle = Rectangle()
testRectangle.height = 10
// 10
testRectangle.width = 15
// 12
์ฌ์ฉํ ๋๋ ์ ์ํ ํ์ ์ ์ด๋ฆ ์์ @๋ฅผ ๋ถ์ฌ์ ์ํ๋ ํ๋กํผํฐ ์์ ๋ถ์ฌ์ฃผ๋ฉด ๋ฉ๋๋ค. ๊ทธ์น.. ์ด๋ฆ์ด property wrapper๋๊น ์๋ฌด๋๋ ํ๋กํผํฐ๋ฅผ ๊ฐ์ธ์ผ๊ฒ ์ฃ ?
struct Rectangle {
private var _height = TwelveOrLess()
private var _width = TwelveOrLess()
var height: Int {
get { _height.wrappedValue }
set { _height.wrappedValue = newValue }
}
var width: Int {
get { _width.wrappedValue }
set { _width.wrappedValue = newValue }
}
}
์ด๋ ๊ฒ special attribute syntax๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์ง์ ํ๋กํผํฐ ๋ํผ๋ฅผ ํ์ฉํ ์ฝ๋๋ฅผ ์์ฑํ ์๋ ์์ต๋๋ค.
property wrapper TwelveOrLess๋ ๊ฒฐ๊ตญ struct์ด๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด๋ฅผ ์์ฑํด์ ๋ณ์์ ํ ๋นํด์ฃผ๋ฉด ํด๋น struct๊ฐ ๊ฐ์ง wrappedValue์ ์ง์ ์ ๊ทผํด์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ทผ๋ฐ ์ด๋ ๊ฒ๊น์ง ํด์ผ๋๋ ?! ์ด๊ฑธ property wrapper ๋ด๋ถ์์ ๋ค ์ฝ๋๋ฅผ ํฉ์ฑํด์ฃผ๊ณ ์๋๊ฑธ ์ด๋ ๊ฒ ์ดํด๋ง ํ๋ฉด ๋๋๊ฑฐ๊ฒ ์ง?ใ ใ ์ด๋ผ๊ณ ์๊ฐํ๊ณ ๋์ด๊ฐ๊ฒ ์ต๋๋ค ๐โ๏ธ
Initialization
ํ์ฌ TwelveOrLess property wrapper๋ ์ ์ ๋น์์ 0์ผ๋ก ๋ํดํธ๊ฐ์ ์ฃผ๊ณ ์์ด์ ์ฌ์ฉํ๋ ํ์ด๋ฐ์๋ ๋ฐ๋ก ๊ฐ์ ์ง์ ํด์ค ์ ์๋ ์ํ์ ๋๋ค! ํ์ง๋ง ์ด๊ธฐ๊ฐ์ด๋ max๊ฐ์ ์์ฑ ๋น์์ ์ ํด์ฃผ๊ณ ์ถ์ ์ ์์์์ ? ๊ทธ๋ฐ ๊ฒฝ์ฐ์ property wrapper์ initializer๋ฅผ ์ ๊ณตํด์ค์ผํฉ๋๋ค.
@propertyWrapper
struct TwelveOrLess {
private var maximum: Int
private var number: Int
var wrappedValue: Int {
get { number }
set { number = min(newValue, 12) }
}
init() {
self.maximum = 12
self.number = 0
}
init(
number: Int
) {
self.maximum = 12
self.number = number
}
init(
number: Int,
maximum: Int
) {
self.maximum = maximum
// ์ฌ๊ธฐ์ number ์ด๊ธฐํํด์ค ๋ wrapped value์ setter์ ๋ค์ด๊ฐ๋ ๋ก์ง์ด ์ ์ฉ๋ผ์ผํจ !!
self.number = min(number, maximum)
}
}
- init()
struct Rectangle {
@TwelveOrLess var height
@TwelveOrLess var width
}
let testRectangle = Rectangle()
testRectangle.height // 0
testRectangle.width // 0
์ด๋ ๊ฒ property wrapper๋ฅผ ์ ์ฉํ ํ๋กํผํฐ์ ์ด๊ธฐ๊ฐ์ ์ฃผ์ง ์๊ณ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, init() ๋ฉ์๋๊ฐ ํธ์ถ๋๋ฉด์ maximum๊ณผ number์ ๊ฐ๊ฐ 12, 0์ผ๋ก ์ด๊ธฐํ๋ฉ๋๋ค.
๋ฐ๋ผ์ ์ด๊ธฐํ ์งํ height์ width์ ์ ๊ทผํด๋ณด๋ฉด ๋ชจ๋ 0์ผ๋ก ์ด๊ธฐํ ๋ผ์๋ ๊ฒ์ ํ์ธํด๋ณด์ค ์ ์์ต๋๋ค.
- init(number:)
struct Rectangle {
@TwelveOrLess var height = 4
@TwelveOrLess var height = 4
}
let testRectangle = Rectangle()
testRectangle.height // 4
testRectangle.width // 4
์๋ ๊ฒ ์ด๊ธฐ๊ฐ์ ์ฃผ๋ ๊ฒฝ์ฐ์๋ init(number:) ํธ์ถ๋๋ฉด์ ํด๋น ๊ฐ์ผ๋ก number๊ฐ ์ด๊ธฐํ๋ฉ๋๋ค.
- init(number:maximum:)
struct Rectangle {
@TwelveOrLess(number: 10, maximum: 5) var height
@TwelveOrLess(number: 6, maximum: 4) var height
}
let testRectangle = Rectangle()
testRectangle.height // 5
testRectangle.width // 4
์ด๋ ๊ฒ property wrapper์ ์์น ๋ค์ initializer์ฒ๋ผ ๊ฐ์ ์ ๊ณตํ ์๋ ์๋ค๋๋ฐ์ !!
์ด๋ฐ ๊ฒฝ์ฐ์๋ ๋น์ฐํ init(number:maximum:)๊ฐ ํธ์ถ๋๊ฒ ์ฃ ?
- mixed
struct Rectangle {
@TwelveOrLess(maximum: 5) var height = 3
@TwelveOrLess var height = 3
}
์ด๋ฐ ์์ผ๋ก ๊ฐ ํ๋กํผํฐ๋ณ๋ก ๋ค๋ฅธ initializer๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค ~~
Projected value
property wrapper๋ projected value๋ผ๋ ๊ฐ๋ ์ ๊ฐ๊ณ ์์ต๋๋ค.
์ถ๊ฐ์ ์ธ ์ ๋ณด๋ฅผ ์ ๋ฌํ ์ ์๋ ๋ณ์๋ก ํด๋น property wrapper๋ก ๊ฐ์ผ ํ๋กํผํฐ ์์ $๋ฅผ ๋ถ์ฌ์ ์ ๊ทผํ ์ ์์ต๋๋ค.
ํ์ ์ ์ด๋ ํ ํ์ ๋ ๋ค ์ฌ ์ ์์ต๋๋ค.
์๋์ ์์์์๋ ํ๋์ ๊ฐ๋ง ์ ๋ฌํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ Bool Type์ผ๋ก ์ ์ธ๋ผ์์ง๋ง ๋ง์ฝ ์ฌ๋ฌ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํด์ผํ๋ค๋ฉด ์ด๋ ํ ํด๋์ค ํ์ ์ด๋ผ๋์ง… ํ์ํ ๋ชจ๋ ํ์ ์ผ๋ก ์ ์ธ์ด ๊ฐ๋ฅํฉ๋๋ค. + self ๋ฆฌํด๋ ๊ฐ๋ฅ!
wrappedValue์ฒ๋ผ projectedValue๋ผ๋ ์ด๋ฆ์ผ๋ก ๋ฐ๋์ ์ ์ธํด์ค์ผํฉ๋๋ค.
@propertyWrapper
struct TwelveOrLess {
private var number: Int
private(set) var projectedValue: Bool
init() {
self.number = 0
self.projectedValue = false
}
var wrappedValue: Int {
get {
number
}
set {
if newValue > 12 {
number = 12
projectedValue = true
} else {
number = newValue
projectedValue = false
}
}
}
}
struct Rectangle {
@TwelveOrLess var height: Int
@TwelveOrLess var width: Int
}
let testRectangle = Rectangle()
testRectangle.height = 4
testRectangle.$height // false
testRectangle.width = 55
testRectangle.$width // true
wrappedValue์ set ๋ก์ง ๋ด๋ถ์์ projectedValue์ ๊ฐ์ ์ค์ ํด์ค์ผ๋ก์จ
projectedValue๋ฅผ ํตํด wrappedValue์ ๊ฐ ๋ณด์ ์ฌ๋ถ๋ฅผ ์ ์ ์์ต๋๋ค!
์ด๋ ๊ฒ ํ์ฉํ๋ฉด ์ ๋ง ํธํ ๊ฒ ๊ฐ์์ !!
enum Size {
case small, large
}
struct Rectangle {
@TwelveOrLess var height: Int
@TwelveOrLess var width: Int
mutating func resize(to size: Size) -> Bool {
switch size {
case .small:
height = 10
width = 20
case .large:
height = 100
width = 100
}
return $height || $width
}
}
๊ทธ๋ฆฌ๊ณ ๊ตฌ์กฐ์ฒด ๋ด๋ถ์์ ์๊ธฐ ์์ ์ property์ projectedValue์๋ ์ ๊ทผํ ์ ์์ต๋๋ค.
์ด๋ฅผ ํตํด์ height ํน์ width ์ค ํ๋๋ผ๋ ๊ฐ์ด ๋ณด์ ๋๋์ง์ ๋ํ ์ฌ๋ถ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
Property wrapper ๊ฐ๋ ์ ๋ํด์๋ ์ด์ ๊ฐ์ ์ก์ ๊ฒ ๊ฐ๊ตฌ
ํ์ฌ์์๋ ํ์ฉํ๊ณ ์๋ property wrapper ์ฝ๋๊ฐ ์๋๋ฐ ์์ง ์ ๋๋ก ์ดํด๋ฅผ ๋ชปํ ๊ฒ ๊ฐ์์
๋ค์์๋ property wrapper๋ฅผ ํ์ฉํ ์์ ์ฝ๋๋ฅผ ๋ฏ์ด๋ณด๋ ์๊ฐ & ์์ง ํท๊ฐ๋ฆฌ๋ ๋ถ๋ถ์ ๋ํด ์ ๋ฆฌํด๋ณด๋ ์๊ฐ์ ๊ฐ์ ธ๋ณด๊ฒ ์ต๋๋ค ๐โ๏ธ
'๐ iOS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Swift] defer๋ฅผ ์ด๋ป๊ฒ ์จ์ผ ์ ์ผ๋ค๊ณ ์๋ฌธ์ด ๋ ๊น (3) | 2024.01.05 |
---|---|
[Swift] rethrows ํค์๋๋ ์ธ์ ์ฐ๋๊ฑธ๊น ๐ค (3) | 2024.01.02 |
[Coordinator] Coordinators Redux (4) | 2023.12.29 |
[Coordinator] The Coordinator (4) | 2023.12.28 |