# 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의 상태를 알 수 있게 하는 값