## 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는 그게 바뀐지 인식을 못함!!