## SwiftUI Property wrapper
> @State
```swift
struct User {
var firstName = ""
var lastName = ""
}
struct ContentView: View {
@State private var user = User()
var body: some View {
VStack {
Text("당신의 이름은 \(user.firstName)\(user.lastName) 입니다")
.font(.title)
.fontWeight(.bold)
.padding(30)
List {
Section(header: Text("이름을 입력하세요").font(.headline)) {
TextField("성", text: $user.firstName)
TextField("이름", text: $user.lastName)
}
}
}
}
}
```
- 사용자가 상태를 변경할 때 그 값을 State안에 넣으면 변경할 때마다 (쓰이는)뷰를 렌더링 하게 된다.
- 이것을 사용하기 위해서는 @State와 Struct를 필수적으로 사용해야 한다.
- Struct 내부의 값이 전체 Struct를 변경할 때마다 전체 구조체가 자동적으로 변경된다.
<br>
> @ObservedObject / @Published
@State는 `특정 view에서만 사용하는 프로퍼티` 였다면,
@ObservedObject는` 여러 view에서 공유할 수 있는 커스텀 타입이 있는 경우나 여러 프로퍼티나 메서드가 있는 경우`, 즉 **복잡한 프로퍼티**에 사용된다.
<br>
주의
> ❗️ 1. String이나 integer 같은 간단한 로컬 프로퍼티 대신 외부 참조 타입을 사용한다는 점을 제외하면 @State와 매우 유사.
> ❗️ 2. @ObservedObject와 함께 사용하는 타입은 ObservableObject 프로토콜을 따라야 함.
> ❗️ 3. @Observed object가 데이터가 변경되었음을 view에 알리는 방법은 여러 가지가 있지만 가장 쉬운 방법은 @Published 프로퍼티 래퍼를 사용하는 것. = SwiftUI에 view reload를 트리거.
예시
```swift
class UserSettings: ObservableObject {
// @ObservedObject를 사용하기위해 @Published를 할당
@Published var score = 0
}
struct ContentView: View {
// @state를 지우고 @ObervedObject로 바꿔줌
// view가 외부 객체를 감지하게 해주는 역할
@ObservedObject var settings = UserSettings()
var body: some View {
VStack {
Text("나의 점수는 \(settings.score)점 입니다.")
Button(action: {
self.settings.score += 1
}) {
Text("Increase Score")
}
}
}
}
```
score에 @Published가 붙었기 때문에 이 score가 변경되면 view를 reload하게 된다.
> 참조타입이 아닌 struct로 해주고 싶을 때
```swift
struct UserSettings {
var score = 0
}
struct ContentView: View {
@State var settings = UserSettings()
var body: some View {
VStack {
Text("나의 점수는 \(settings.score)점 입니다.")
Button(action: {
self.settings.score += 1
}) {
Text("Increase Score")
}
}
}
}
```
> @StateObject
WWDC 2020에서 애플은 @StateObject를 추가로 공개했다.
@ObservedObject와 거의 같은 방식으로 작동한다.
SwiftUI가 View를 다시 랜더링 할 때, 실수록 취소되는 것을 방지해준다고 한다.
```swift
struct ContentView: View {
@StateObject var user = User()
}
```
> @EnvironmentObject
- @EnvironmentObject는 보통 앱 전반에 걸쳐 공유되는 데이터에 사용된다.
- @EnvironmentObject는 .environmentObject()를 통해 값을 전달할 수 있다.
- 전달하는 object는 ObservableObject 프로토콜을 준수해야 한다.
- 아래 코드와 같이 root view를 제공하면, 어떠한 view에서도 사용이 가능하다.
```swift
// MySettings.swift
class Settings: ObservableObject {
@Published var version = 0
}
// SceneDelegate.swift
var settings = UserSettings()
window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(settings))
// MyViews.swift
struct ContentView: View {
@EnvironmentObject var settings: UserSettings
var body: some View {
NavigationView {
VStack {
Button(action: {
self.settings.version += 1
}) {
Text("Increase version")
}
NavigationLink(destination: DetailView()) {
Text("Show Detail View")
}
}
}
}
}
struct DetailView: View {
@EnvironmentObject var settings: UserSettings
var body: some View {
Text("Version: \(settings.version)")
}
}
```
여기까지...만....!
👏 struct는 값이 바뀌면 바로 메모리 할당을 해서 알 수 있는데
class는 그게 바뀐지 인식을 못함!!