---
# System prepended metadata

title: Untitled

---

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