[SwiftUI] @State로 알아보는wrappedValue, projectedValue

miori·2022년 11월 25일
0

ios-swiftUI

목록 보기
4/4
post-thumbnail

SwiftUI 를 공부하면서, 프로퍼티래퍼를 사용하고 $(달러사인)를 사용하여 값을 전달해주기도 하였다.
이때 사용되는 개념인 wrappedValue와 projectedValue에 대해 자세히 공부해보고 싶어졌다.

SwiftUI @State 정의

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
@frozen @propertyWrapper public struct State<Value> : DynamicProperty {

    /// Creates the state with an initial wrapped value.
    ///
    /// Don't call this initializer directly. Instead, declare a property
    /// with the ``State`` attribute, and provide an initial value:
    ///
    ///     @State private var isPlaying: Bool = false
    ///
    /// - Parameter wrappedValue: An initial wrappedValue for a state.
    public init(wrappedValue value: Value)

    /// Creates the state with an initial value.
    ///
    /// - Parameter value: An initial value of the state.
    public init(initialValue value: Value)

    /// The underlying value referenced by the state variable.
    ///
    /// This property provides primary access to the value's data. However, you
    /// don't access `wrappedValue` directly. Instead, you refer to the property
    /// variable created with the ``State`` attribute. In the following example,
    /// the button's label depends on the value of `isPlaying` and its action
    /// toggles the value of `isPlaying`. Both of these accesses implicitly
    /// rely on the state property's wrapped value.
    ///
    ///     struct PlayButton: View {
    ///         @State private var isPlaying: Bool = false
    ///
    ///         var body: some View {
    ///             Button(isPlaying ? "Pause" : "Play") {
    ///                 isPlaying.toggle()
    ///             }
    ///         }
    ///     }
    ///
    public var wrappedValue: Value { get nonmutating set }

    /// A binding to the state value.
    ///
    /// Use the projected value to pass a binding value down a view hierarchy.
    /// To get the `projectedValue`, prefix the property variable with a dollar
    /// sign (`$`). In the following example, `PlayerView` projects a binding
    /// of the state property `isPlaying` to the `PlayButton` view using
    /// `$isPlaying`:
    ///
    ///     struct PlayerView: View {
    ///         var episode: Episode
    ///         @State private var isPlaying: Bool = false
    ///
    ///         var body: some View {
    ///             VStack {
    ///                 Text(episode.title)
    ///                     .foregroundStyle(isPlaying ? .primary : .secondary)
    ///                 PlayButton(isPlaying: $isPlaying)
    ///             }
    ///         }
    ///     }
    ///
    public var projectedValue: Binding<Value> { get }
}

@State의 정의를 보면 위와 같다.

주석으로 상당히 설명이 자세히 되어있다.

정리해보면 다음과 같다.

  • wrappedValue로 초기값을 정의
  • 뷰 계층 아래로 값을 전달하고자 할때 binding value 사용
  • projectedValue값을 얻으려면 $ 달러사인 사용

이를 통해 초기값은 wrappedValue로 정의하고 이후, projectedValue를 통해 Binding 타입이 반환이 됨을 알 수 있다.

실제로 Swift 5.1 에서 추가된 Property Wrapper의 개념이 잘 적용이 된 것을 알 수 있다.

profile
iS를 공부하는 miori 입니다.

0개의 댓글