Property Wrapper
ํ๋กํผํฐ ๋ํผ๋ ํ๋กํผํฐ๋ฅผ ํน์ ํ์ ์ผ๋ก ๊ฐ์ธ์ ์ถ๊ฐ์ ์ธ ๋์์ด๋ ๊ธฐ๋ฅ์ ๊ฐ์ง ํ๋กํผํฐ๋ฅผ ์ ์ธํ ๋ ์ฌ์ฉํฉ๋๋ค.
์ฆ, ํด๋น ๋ณ์์ ์ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ์ ๋ถ์ฌ์ฃผ๋ ๋ฌธ๋ฒ์ ๋๋ค.
์๋ ๋ค์ฏ ๊ฐ์ง ํ๋กํผํฐ ๋ํผ์ ๋ํด์ ๊ณต๋ถํด๋ณด์์ต๋๋ค.
- State
- Binding
- ObservableObject
- EnvironmentObject
- Environment
@State
State ํ๋กํผํฐ ๋ํผ๋ ๊ตฌ์กฐ์ฒด(Struct) ๋ด์ ํ๋กํผํฐ๋ฅผ ์์ ํ ์ ์๊ฒ ๋์์ค๋๋ค.
๋ํ State๋ก ์ ์ธ๋ ๋ณ์์ ๊ฐ์ ๋ณ๊ฒฝํ์ ๋ ํด๋น ๋ณ์๋ฅผ ๊ฐ์ ธ๋ค ์ด View๊ฐ ํฌํจ๋ body ์ ์ฒด๋ฅผ ๋ค์ ๊ทธ๋ ค์ค๋๋ค.
struct PlayButton: View {
@State private var isPlaying: Bool = false // Create the state.
var body: some View {
Button(isPlaying ? "Pause" : "Play") { // Read the state.
isPlaying.toggle() // Write the state.
}
}
}
@Binding๋ฅผ ํตํด ํ์ ๋ทฐ์ ์ํ ๊ณต์
State ํ๋กํผํฐ ๋ํผ๋ฅผ ํตํด ๊ฐ์ ํ์ ๋ทฐ์ ์ ๋ฌํ๋ฉด ํด๋น ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ํ์ ๋ทฐ๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค.
ํ์ง๋ง ํ์ ๋ทฐ์์๋ ๊ฐ์ ์์ ํ ์ ์์ต๋๋ค. ํ์ ๋ทฐ์์ State๋ฅผ ํตํ ๊ฐ์ ์์ ํ ์ ์๋๋ก ํ๋ ค๋ฉด Binding ํ๋กํผํฐ ๋ํผ๊ฐ ํ์ํฉ๋๋ค.
Binding์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ์์ฑ๊ณผ ๋ฐ์ดํฐ๋ฅผ ํ์ํ๊ณ ๋ณ๊ฒฝํ๋ ๋ทฐ ๊ฐ์ ์๋ฐฉํฅ ์ฐ๊ฒฐ์ ๋ง๋ญ๋๋ค.
์์ ๋ทฐ์ธ PlayerView์์ isPlaying์ด๋ผ๋ ํ๋กํผํฐ๋ฅผ State๋ก ์ ์ธํฉ๋๋ค. ์ดํ ํ์ ๋ทฐ์ธ PlayButton์ isPlaying์ ์ํ๋ฅผ ๊ณต์ ํด์ฃผ๊ธฐ ์ํด Binding์ ์ฌ์ฉํด์ค๋๋ค.
ํ์ ๋ทฐ์ ํ๋กํผํฐ์ ๊ณต์ ๋ฅผ ํ๊ธฐ ์ํด์๋ $๊ธฐํธ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ ๋๊ฒจ์ฃผ์ด ์ฌ์ฉํฉ๋๋ค.
struct PlayerView: View {
@State private var isPlaying: Bool = false // Create the state here now.
var body: some View {
VStack {
PlayButton(isPlaying: $isPlaying) // Pass a binding.
}
}
}
struct PlayButton: View {
@Binding var isPlaying: Bool // Play button now receives a binding.
var body: some View {
Button(isPlaying ? "Pause" : "Play") {
isPlaying.toggle()
}
}
}
.constant
๋ณ๊ฒฝํ ์ ์๋ ๊ณ ์ ๋ ๊ฐ์ผ๋ก Binding์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋๋ค.
์์ ๋ทฐ๋ก๋ถํฐ State ๋ณ์๋ฅผ ๋๊ฒจ๋ฐ๊ธฐ ํ๋ Preview์์ ์ฃผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
PlayButton(isPlaying: Binding.constant(true)) // .constant(true) ํํ๋ก๋ ์ฌ์ฉ ๊ฐ๋ฅ
ObservableObject
@State๋ ๊ฐ ํ์ ์ ๋ณ์๋ง ๊ฐ์งํ๊ธฐ ๋๋ฌธ์ ์ฐธ์กฐ ํ์ ์ ๋ณ์๋ ๊ฐ์งํ์ง ๋ชปํ๋ค๋ ๋จ์ ์ด ์์ต๋๋ค.
๋ฐ๋ผ์ ์ฐธ์กฐ ํ์ ์ธ Class๋ฅผ ๊ฐ์งํ๊ธฐ ์ํด์๋ ObservableObject, @Published, @ObservedObject๋ฅผ ์ฌ์ฉํ์ฌ ํ๋์ ๊ธฐ๋ฅ์ ์์ฑํ ์ ์์ต๋๋ค.
๊ฐ์ง๋์ด์ผ ํ ํด๋์ค์๋ ObservableObject ํ๋กํ ์ฝ์ ์ฑํํฉ๋๋ค.
ํด๋น ํด๋์ค ๋ด๋ถ์์ ๊ฐ์ง๋์ด์ผ ํ ํ๋กํผํฐ์๋ @Published ํ๋กํผํฐ ๋ํผ๋ฅผ ๋ถ์ฌ ๊ฐ์งํฉ๋๋ค.
ํด๋น ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ธฐ ์ํด์๋ @ObservedObject ํ๋กํผํฐ ๋ํผ๋ฅผ ๋ถ์ฌ ํด๋์ค๋ฅผ ์์ฑํฉ๋๋ค.
class NumberCounter: ObservableObject {
@Published var number: Int = 0
func increaseNumber() {
number += 1
}
}
struct ContentView: View {
@ObservedObject var numberCounter = NumberCounter()
var body: some View {
VStack {
Text("\(self.numberCounter.number)")
Button {
self.numberCounter.increaseNumber()
} label: {
Text("Plus One")
}
}
}
}
@StateObject
View๊ฐ ์ฌ์์ฑ๋ ๋ View์์ ์ ์ธ๋ @ObservedObject ๋ํ ์ฌ์์ฑ๋ฉ๋๋ค. ๋ฐ๋ผ์ ํด๋์ค ๋ด์์ ๊ฐ์ง๋๊ณ ์๋ Published ํ๋กํผํฐ ๋ํผ์ ๋ณ์ ๊ฐ๋ ์ด๊ธฐํ๋ฉ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์๋ @ObservedObject๋ฅผ @StateObject๋ก ๋ณ๊ฒฝํ์ฌ View์ ์ฌ์์ฑ๊ณผ ์๊ด ์์ด ํด๋์ค์ ์ธ์คํด์ค๊ฐ ์๋ฉธ๋๊ฑฐ๋ ์ฌ์์ฑ๋์ง ์๋๋ก ํ ์ ์์ต๋๋ค.
@StateObject var numberCounter = NumberCounter()
๋ง์ฝ ์์ ๋ทฐ์ ํ์ ๋ทฐ๊ฐ ์กด์ฌํ๊ณ , ํ์ ๋ทฐ์ @ObservedObject ์ ์ธ๋์ด ์์ ๊ฒฝ์ฐ์, @StateObject๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ํ์ ๋ทฐ์ @ObservedObject๋ฅผ ์์ ๋ทฐ๋ก ์ฎ๊ฒจ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค.
์์ ๋ทฐ์ State ๋ฑ์ ํตํด ๋ทฐ๊ฐ ์ฌ์์ฑ๋๋ฉด ํ์ ๋ทฐ๋ ์ฌ์์ฑ๋ ์๋ฐ์ ์์ต๋๋ค.
์๋์ ๊ฐ์ด ํด๊ฒฐํ๋ฉด NumberCounter์ ๋ฐ์ดํฐ๋ ํ์ ๋ทฐ์ ๋ฐ๊นฅ์ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ์์ ๋ทฐ๊ฐ ์ฌ์์ฑ๋ ๊ฒ์ ์๋๋๋ค. ๋ฐ๋ผ์ ๋ฐ์ดํฐ๋ ๋ณด์กด๋๊ณ , ๊ทธ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ์ผ๋ก ํ์ ๋ทฐ๊ฐ ๊ทธ๋ ค์ง ์ ์์ต๋๋ค.
// ์์ ๋ทฐ
struct ContentView: View {
@ObservedObject var numberCounter = NumberCounter()
var body: some View {
VStack {
SubView(numberCounter: numberCounter)
}
}
}
// ํ์ ๋ทฐ
struct SubView: View {
@ObservedObject var numberCounter: NumberCounter
var body: some View {
VStack {
// ...
}
}
}
@EnvironmentObject
@ObservedObject ๋๋ @StateObject๋ก ์ฌ์ฉํ์ฌ ํด๋์ค ์ธ์คํด์ค๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์์ต๋๋ค.
ํ์ง๋ง ์ฌ๊ธฐ์ ํ์ ๋ทฐ์ ํ์ ๋ทฐ, ๊ทธ๋ฆฌ๊ณ ๊ทธ ํ์ ๋ทฐ๊ฐ ๊ณ์ํด์ ์์ฑ๋๊ณ ๊ฐ์ ๊ณ์ํด์ ์ ๋ฌํด์ฃผ์ด์ผ ํ ๊ฒฝ์ฐ์๋ @ObservedObject๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ์ฌ์ฉํด์ฃผ์ด์ผ ํ๋ ๋ถํธํจ์ด ์กด์ฌํฉ๋๋ค.
๋ฐ๋ผ์ @ObservedObject๋ ๊ฐ๊น์ด ํ์ ๋ทฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๊ธฐ์ ์ ํฉํฉ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ @EnvironmentObject๋ฅผ ์ฌ์ฉํ์ฌ ํ์ ๋ทฐ๋ก ์ง์ ์ ๋ฌํ๋ ๊ฒ์ด ์๋ ๋ทฐ์ environment๋ผ๋ ๊ณณ์ ์ ์ฅ๋์ด ์ฌ๋ฌ ํ์ ๋ทฐ๊ฐ ์กด์ฌํด๋ ๊ฐ์ ๊ณ์ธต์๋ง ์๋ค๋ฉด EnvironmentObject๋ฅผ ๊ฐ์ ธ๋ค ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ต์์ ๋ทฐ์ ์กด์ฌํ๋ ๋ฐ์ดํฐ๋ฅผ ํ์ ๋ทฐ ์ด๋์๋ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ฏ๋ก ์ฑ ์ ๋ฐ์ ๊ฑธ์ณ ์ฌ์ฉ๋๋ ๋ฐ์ดํฐ ์ ๋ฌ์ ์ ํฉํฉ๋๋ค.
// ์์ ๋ทฐ
struct ContentView: View {
@ObservedObject var numberCounter = NumberCounter()
var body: some View {
VStack {
SubView()
.environmentObject(numberCounter)
}
}
}
// ํ์ ๋ทฐ
struct SubView: View {
@EnvironmentObject var numberCounter: NumberCounter
var body: some View {
VStack {
// ...
}
}
}
@Environment
@Environment๋ @EnvironmentObject์ ๋์ผํ๊ฒ View์ Environment๋ผ๋ ๊ณณ์ ์ ์ฅ์ด ๋ฉ๋๋ค.
ObservableObject ๋ฐ์ดํฐ๋ฅผ ์ง์ Environment์ ์ ์ฅํ์ฌ ์ฌ์ฉํ๋ @EnvironmentObject์๋ ๋ค๋ฅด๊ฒ @Environment๋ ์ด๋ฏธ ์ ์ฅ๋์ด ์๋ ๊ฐ๋ค์ ์ฌ์ฉํฉ๋๋ค.
๋ํ ์ฑ ์์คํ ์ ๋ฐ์ ๊ฑธ์ณ ์ฌ์ฉ๋๋ ์ค์ ์ ์ ๊ทผํ ๋ ์ฌ์ฉํ๊ธฐ์ ์ ํฉํฉ๋๋ค.
@Environment(\.colorScheme) var colorScheme