J
[SwiftUI] @State, @Binding 본문
`@State`와 `@Binding`은 SwiftUI에서 상태 관리와 데이터 전달을 위한 핵심 속성 래퍼.
이들 속성 래퍼를 사용하면 SwiftUI에서 선언적 방식으로 UI를 업데이트 가능.
1. `@State`
`@State`는 로컬 상태를 저장하는 데 사용.
이는 뷰 내에서만 소유되고 수정 가능한 상태를 의미.
`@State`로 선언된 변수의 값이 변경될 때마다 해당 값을 사용하는 뷰가 자동으로 리렌더링.
struct CounterView: View {
@State private var count = 0 // 뷰의 로컬 상태
var body: some View {
VStack {
Text("Count: \\\\(count)")
Button("Increment") {
count += 1 // count가 변경될 때마다 뷰가 업데이트됨
}
}
}
}
- `@State`는 뷰가 자체적으로 관리하는 상태를 나타내며, `private`로 선언하는 것이 일반적.
- 변수 값이 변경되면 SwiftUI는 뷰를 다시 렌더링하여 최신 상태를 반영.
2. `@Binding`
`@Binding`은 상위 뷰에서 하위 뷰로 전달되는 상태를 공유하는 데 사용.
`@Binding`을 통해 하위 뷰에서 값을 수정하면 상위 뷰의 상태도 함께 업데이트.
이 방식은 여러 뷰가 동일한 데이터를 공유하거나 상위 뷰의 상태를 자식 뷰에서 제어할 때 유용.
struct CounterView: View {
@State private var count = 0 // 상위 뷰의 상태
var body: some View {
VStack {
Text("Count: \\\\(count)")
IncrementButton(count: $count) // @Binding을 통해 하위 뷰에 전달
}
}
}
struct IncrementButton: View {
@Binding var count: Int // 상위 뷰의 상태를 참조
var body: some View {
Button("Increment") {
count += 1 // count를 업데이트하면 상위 뷰의 count도 업데이트됨
}
}
}
- `@Binding`은 상위 뷰의 상태에 대한 참조 역할을 하여, 상위 뷰와 하위 뷰 간의 상태 동기화를 가능하게 함.
- `@Binding`변수는 값을 직접 소유하지 않고 상위 뷰에서 받아오기 때문에 초기값을 지정하지 않음.
3. `@State`와 `@Binding`의 차이점 요약
속성 래퍼 | 설명 | 사용 시기 |
`@State` | 뷰 내부에서 로컬 상태로 사용되고, 해당 뷰의 소유 상태를 나타냄 | 뷰의 상태를 뷰 내부에서만 관리할 때 |
`@Binding` | 다른 뷰의 상태를 참조하는 용도로 사용되며, 상위 뷰에서 데이터를 제어할 수 있음 | 상위 뷰의 상태를 하위 뷰에 전달할 때 |
4. `@State`와 `@Binding`의 사용 시 주의 사항
- `@State`는 뷰의 로컬 상태만을 관리하므로 다른 뷰에서 직접 참조할 수 없음.
- `@Binding`은 초기값을 설정하지 않으며, 반드시 상위 뷰의 상태를 바인딩해야 함.
5. `@State`와 `@Binding`의 렌더링 시점 차이
5.1. `@State`의 렌더링 시점
- `@State`는 뷰의 자체 상태를 소유하고 관리. 따라서 `@State`가 변경되면 해당 뷰가 다시 렌더링.
- SwiftUI는 `@State` 변수를 감지하여 상태가 변경되면 해당 뷰를 재생성하여 최신 상태를 반영.
- 독립적으로 관리되는 상태이기 때문에 상위나 다른 뷰에 영향을 주지 않고 해당 뷰의 상태만 업데이트.
struct CounterView: View {
@State private var count = 0 // 뷰의 자체 상태
var body: some View {
VStack {
Text("Count: \\\\(count)")
Button("Increment") {
count += 1 // count가 변경되면 CounterView만 다시 렌더링
}
}
}
}
- 위 예시에서 `count`가 변경되면 `CounterView`는 다시 렌더링되지만, 다른 뷰는 영향을 받지 않음.
5.2. `@Binding`의 렌더링 시점
- `@Binding`은 상위 뷰에서 전달된 상태에 참조를 제공하는 방식으로 사용.
- `@Binding`으로 선언된 변수는 상위 뷰의 상태에 대한 연결을 유지하고, 이 상태가 변경되면 해당 하위 뷰도 자동으로 다시 렌더링.
- 즉, 상위 뷰의 상태 변경이 하위 뷰의 렌더링을 트리거.
- 하위 뷰에서 `@Binding` 변수를 수정하면 상위 뷰의 상태가 업데이트되며, 상위 뷰와 하위 뷰가 동기화.
struct MainView: View {
@State private var isOn = false // 상위 뷰 상태
var body: some View {
VStack {
Text("Switch is \\\\(isOn ? "ON" : "OFF")")
ToggleButton(isOn: $isOn) // 하위 뷰에 전달
}
}
}
struct ToggleButton: View {
@Binding var isOn: Bool // 상위 뷰의 상태 참조
var body: some View {
Button("Toggle") {
isOn.toggle() // 상위 뷰의 상태 업데이트
}
}
}
- `ToggleButton`에서 `isOn.toggle()` 호출 시, `MainView`의 `isOn`이 변경되며, 이는 `MainView`와 `ToggleButton` 모두 재렌더링 트리거.
6. `@State`와 `@Binding`의 렌더링 흐름 차이 요약
속성 래퍼 | 소유/참조 | 렌더링 트리거 | 렌더링 범위 |
`@State` | 소유 | `@State` 변수 자체의 값이 변경될 때 | 해당 뷰만 다시 렌더링 |
`@Binding` | 참조 | 상위 뷰에서 바인딩한 상태가 변경될 때, 또는 하위 뷰에서 `@Binding` 변수 업데이트 시 | 상위 뷰와 하위 뷰가 모두 다시 렌더링 |
7. `@State`와 `@Binding`의 렌더링 시점 관련 주의 사항
- `@State`는 개별 뷰의 독립적인 상태로 다뤄져 다른 뷰의 상태 변경과 상관없이 독립적인 렌더링.
- 반면 `@Binding`은 상위 뷰와의 상태 동기화를 제공하기 때문에 상위 뷰 상태가 변경되면 하위 뷰의 렌더링에 영향을 미침.
- 이는 상위 뷰와 하위 뷰 간 상태 동기화를 유지해야 할 때 유용하지만, 불필요한 렌더링을 초래할 수 있음.
- 예를 들어, `@Binding`이 여러 개의 하위 뷰로 전달되면, 상위 뷰의 상태 변경으로 인해 모든 하위 뷰가 다시 렌더링될 수 있음.
- 최적화가 필요한 경우에는 필요한 하위 뷰에만 상태를 전달하거나 `ObservableObject`를 사용하여 상태 변경이 필요한 뷰에만 반영되도록!
'SwiftUI' 카테고리의 다른 글
[SwiftUI] NavigationView vs NavigationStack (0) | 2024.05.09 |
---|---|
[SwiftUI] SwiftUI의 View Rendering (0) | 2024.05.08 |
[SwiftUI] ViewModifier, modifier(_:) (0) | 2024.05.03 |
[SwiftUI] Source of Truth (0) | 2024.04.29 |
[SwiftUI] @State와 @Binding의 projectedValue ($) (0) | 2024.04.29 |