Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Archives
Today
Total
관리 메뉴

J

[SwiftUI] @State, @Binding 본문

SwiftUI

[SwiftUI] @State, @Binding

yujaehui 2024. 4. 29. 15:16

`@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`를 사용하여 상태 변경이 필요한 뷰에만 반영되도록!