# Swift UI Prperty Wraaper ## @State - 개체 내부에서 사용되며 뷰 View가 에 대한 변경 사항에 응답할 수 있도록함 - 뷰가 포함된 뷰가 소유한 속성에 대해 사용 - 뷰는 @State속성 자체를 초기화 - 다른 개체에서 속성을 받지 않음 - 뷰 자체에 의해 관리되는 상태에 적합 - 새로 고침 중에 뷰 인스턴스를 삭제하고 다시 생성해야 할 때 유지되어야 함 - private을 사용하는 것이 일반적이며, 외부 소스가 @State속성을 수정해서는 안됨 ### @State를 사용하는 경우 - View자체에서 wrapping할 인스턴스를 만들고 소유해야 할 때 - wrapping된 인스턴스 내에서 발생하는 변경사항에 대항해야 할 때 - 값을 wrapping 할 때 ## @Binding - 다른 View에서 전달된 Property를 사용할 때 - 바인딩을 받는 뷰는 바인딩된 Property를 읽고 외부 소스(예: 상위 뷰)의 변경 사항에 응답할 수 있으며 속성에 대한 쓰기 액세스 권한이 있음 - @Binding을 업데이트하면 제공한 뷰의 해당 Property가 업데이트 된다는 의미 ### @Binding을 사용하는 경우 - 상위 뷰가 소유한 Property에 대한 읽기 및 쓰기 액세스 권한이 필요할 때 ## @StateObject - 참조 유형이며, Property 중 하나가 변경될 때마다 Swift UI에 알림 - State + ObservedObject 느낌 ### @StateObject를 사용하는 경우 - Property의 변경 또는 업데이트에 응답하려고 할 때 ## @ObservedObject - 사용되는 뷰에서 생성하거나 소유하지 않은 인스턴스를 래핑하는데 사용 (ObservableObject) - @StateObject의 기능과 거의 유사 - 대부분 ViewModel을 선언할 때 사용하는 프로퍼티래퍼 - ViewModel에서 변경사항이 있다면 뷰를 다시 그릴수 있도록 해주는 역할 ### @ObservedObject을 사용하는 경우 - Property의 변경 또는 업데이트에 응답하려고 할 때 ## @EnvironmentObject - 같은 오브젝트를 여러 곳에서 사용할 때 ## @StateObject와 @ObservedObject의 차이는 무엇인가요? - ObservedObject는 값의 변화가 있을 때, View 전체를 다시 그리고, StateObject는 변화된 값이 있는 View만 다시 그립니다. 따라서 ObservedObject는 View Life Cycle의 영향을 받고, StateObject는 View Life Cycle의 영향을 받지 않습니다. ### 출처 [SwiftUI Property Wrapper](https://swiftuipropertywrappers.com/) --- SwiftUI Property Wrapper 정리 ### @State > A property wrapper type that can read and write a value managed by SwiftUI. 해당 변수의 값이 바뀌면, SwiftUI가 View를 자동으로 업데이트 함 ### @Binding > A property wrapper type that can read and write a value owned by a source of truth. View간의 양방향 바인딩을 위해 사용 ex) ```swift struct MainView: View { @State private var isPlay = false var body: some View { VStack(spacing: 20) { PlayButton(isPlaying: $isPlay) Button(isPlay ? "재생중" : "정지중") { isPlay.toggle() } .buttonStyle(.borderedProminent) } } } struct PlayButton: View { @Binding var isPlaying: Bool var body: some View { Image(systemName: isPlaying ? "play.fill" : "pause.fill") .resizable() .foregroundColor(isPlaying ? .red : .black) .frame(width: 100, height: 100) .animation(.default, value: isPlaying) .onTapGesture { isPlaying.toggle() } } } ``` ### @Published > A type that publishes a property marked with an attribute. ### @ObservableObject > A type of object with a publisher that emits before the object has changed. object가 바뀌면, 값을 방출한다 ### @ObservedObject > A property wrapper type that subscribes to an observable object and invalidates a view whenever the observable object changes. observable object를 구독하고있고, observable object가 바뀌면 view를 업데이트 한다 ```swift import SwiftUI final class MainViewModel: ObservableObject { @Published var state: Bool = false } struct MainView_ViewModel: View { @ObservedObject var viewModel: MainViewModel var body: some View { PlayButton(isPlaying: $viewModel.state) } } ``` ### @StateObject > A property wrapper type that instantiates an observable object. ### @EnvironmentObject > A property wrapper type for an observable object supplied by a parent or ancestor view. parent나 더 위의 parent들의 데이터를 공유할 수 있게 해줌 ```swift struct MainView_EnvironmentObject: View { @EnvironmentObject var viewModel: MainViewModel var body: some View { VStack(spacing: 32) { PlayButton(isPlaying: $viewModel.state) ChildView() } } } struct ChildView: View { @EnvironmentObject var viewModel: MainViewModel var body: some View { PlayButton(isPlaying: $viewModel.state) } } ``` ### @Environment > A property wrapper that reads a value from a view’s environment. view의 상태를 알 수 있게 하는 값