# SwiftUI

1. ﻿﻿@State: 뷰 내부에서 관리되는 로컬 상태값을 저장.
2. ﻿﻿﻿@Binding: 부모 뷰로부터 받은 값에 대한 참조를 가짐.
3. ﻿﻿@observedObject: 외부 클래스의 상태를 추적하고 뷰를 업데이트.
4. ﻿﻿@Environmentobject: 앱 전체에서 공유되는 상태 객체를 사용.
5. ﻿﻿@Published:ObservableObject의 속성을 업데이트할 때 View를 자동 리프레시
6. ﻿﻿@AppStorage: UserDefaults에 값을 저장하고 불러올 때 사용.
7. ﻿﻿﻿@SceneStorage: 앱의 'Scene' 세션 간에 데이터를 저장.
8. ﻿﻿@Environment: 시스템 제공 환경 설정에 접근.
9. ﻿﻿@StateObject: 뷰가 소유하고 있는 상태 객체를 생성하고 관리.
10. @FetchRequest: Core Data의 쿼리 결과를 뷰에 연결.

## 0. Property Wrapper (프로퍼티 래퍼)

• 의미: 속성(property)에 추가적인 행동이나 계산을 덧붙여서 사용할 수 있도록 하는 구조.

프로퍼티 래퍼를 사용하면 복잡한 로직이나 계산을 간결하게 표현할 수 있어 코드의 가독성과 재사용성을 향상시킴

## 1. @State

* ﻿﻿정의: 로컬 상태 변수를 선언하고 관리 (간단한 데이터 저장)
* ﻿﻿장점: 코드가 간결하고 이해하기 쉬움.
* ﻿﻿단점: 해당 View 내에서만 사용 가능.
* ﻿﻿언제 사용: View의 로컬 상태를 관리할 때.
* ﻿﻿왜 사용: 상태를 간단하게 추적하고 비를 자동으로 업데이트 하려고
* ﻿﻿어떻게 사용: View 내부에서 @State 어노테이션을 사용하여 변수를 선언

`@State private var count = 0`

사용 예시코드&#x20;

<pre class="language-swift"><code class="lang-swift">struct CounterView: View {
    @State private var count = o
    
    var body: some View {
<strong>        Button ("카운트 증가") {
</strong><strong>        count += 1
</strong><strong>        Text("현재 카운트: 1(count)")
</strong>    }
}
</code></pre>

## 2. @Binding

* ﻿﻿정의: 상위 View의 상태를 하위 View에서 참조하고 조작
* ﻿﻿장점: 데이터 흐름을 명확하게 표현가능
* ﻿﻿단점: 상위 View와 하위 View가 상태에 대해 강하게 연결
* ﻿﻿언제 사용: 상위 View의 상태를 하위 View에서 수정할 필요가 있을 때.
* ﻿﻿왜 사용: 상태를 유연하게 공유하고 관리
* ﻿﻿어떻게 사용: 하위 View에서 @Binding 변수를 선언하고 상위 View에서 연결

`@Binding var isOn: Bool`

사용 예시코드

```swift
struct SwitchView: View {
    @Binding var isOn: Bool
    
    var body: some View {
        Toggle("스위치", isOn: $isOn)
    }
}
```

## 3. @ObservedObject

* ﻿﻿정의: 복잡한 데이터 모델을 View에 바인딩
* ﻿﻿장점: 여러 View에서 공유 가능
* ﻿﻿단점: Observableobject 프로토콜을 적용한 별도의 클래스 필요.
* ﻿﻿언제 사용: 여러 화면에서 공유해야 하는 정보나 복잡한 정보를 기억할 때 여러View에서 공유할때 사용 ( ex. 사용자 프로필 정보와 같은 복잡한 데이터)
* ﻿﻿왜 사용: 상태 변화를 감지하고 UI를 업데이트함!
* ﻿﻿어떻게 사용: @observedobject 어노테이션과 함께 ObservableObject를 적용한 클래스의 인스턴스를 사용

`@Observedobject var viewModel: MyViewModel`

사용 예시코드

<pre class="language-swift"><code class="lang-swift">struct MyView: View {
<strong>    @Observedobject var viewModel: MyViewModel
</strong><strong>    
</strong>    var body: some View {
        Text (viewModel.title)
    }
}
</code></pre>

## 4. @EnvironmentObject

* ﻿﻿정의: 앱 전체에서 공유되는 데이터 객체를 다룸!
* ﻿﻿장점: 앱 전체의 상태를 한 곳에서 관리 가능
* ﻿﻿단점: 명시적인 초기화가 없으면 런타임 에러 발생 가능.
* ﻿﻿언제 사용: 앱 전체에서 공유되는 데이터가 있을 때, 앱의 모든 곳에서 접근해야 하는 큰 정보 담을때 사용 (ex.로그인 상태, 테마 설정)
* ﻿﻿왜 사용: 앱 전체의 상태를 효율적으로 관리합니다.
* ﻿﻿어떻게 사용: @EnvironmentObject 어노테이션을 사용하여 변수를 선언

`@EnvironmentObject var appData: AppData`

사용 예시코드

```swift
struct ContentView: View {
    @EnvironmentObject var appData: AppData
    
    var body: some View {
        Text("전체 사용자 수: V(appData.totaLusers)")
    }
}
```

#### @State, @ObservedObject, @EnvironmentObject 차이점

• 모두 SwiftUI에서 데이터를 관리하고 UI를 업데이트하는 데 사용

#### @State, @Observedobject, @EnvironmentObject 차이점

1. 범위: @State는 하나의 View, @0bservedobject는 여러 View, @EnvironmentObject는 앱 전체에서 사용가능
2. 복잡성: @State는 간단한 데이터, @observedObject와 @Ervironmentobject는 복잡한 데이터 객체 다룰 수 있음!

**@Observedobject와 @EnvironmentObject 공통점**

상태 관리 객체를 View와 연결

**@Observedobject와 @EnvironmentObject 차이점**

@observedObject 는 명시적으로 인스턴스를 전달해야 하며, @Environmentobject는 앱 전체에 주입 된 객체를 자동으로 찾음

**@State와 @Binding 공통점**

상태 변수를 선언

**@State와 @Binding 차이점**

사용하는 방법이 다름. @State는 View 내부에서만 사용되는 상태를 관리, @Binding은 상위 View와 하위 View 사이에서 상태를 공유

## 5. @Published

* ﻿﻿정의: ObservableObject의 속성을 업데이트할 때 View를 자동으로 리프레시(해당 변수가 변경되면 "여기 변했어요! 뷰 다시 그려주세요!"라고 알려주는 역할)
* ﻿﻿장점: 코드가 간결, ObservableObject와 잘 연동됨.
* ﻿﻿단점: 특정 속성에만 적용, 복잡한 상태 관리에는 적합하지 않을 수 있음
* ﻿﻿언제 사용: Observableobject의 특정 속성이 변경될 때 비를 업데이트해야 할 때.
* ﻿﻿왜 사용: 상태 변화를 쉽게 감지하고 UI를 자동으로 업데이트
* ﻿﻿어떻게 사용: @Published 어노테이션을 속성 앞에 추가!
* ﻿﻿사용 예시코드

<pre class="language-swift"><code class="lang-swift">class Counter: ObservableObject {
    @Published var count = 0
<strong>    // 이 변수가 바뀔 때마다 뷰는 자동으로 업데이트 됩니다.
</strong>}

struct ContentView: View {
    @Observedobject var counter = Counter()
    
    var body: some View {
        Text("Count: \(counter.count)")
    }
}
</code></pre>

@Published는 변수가 바뀌면 뷰에 알려주어 자동으로 업데이트되게 하는 매우 유용한 도구

## 6. @AppStorage

* ﻿﻿정의: 사용자 기본 설정을 쉽게 저장하고 조회
* ﻿﻿장점: UserDefaults를 직접 사용하는 것보다 훨씬 간편
* ﻿﻿단점: 복잡한 데이터 구조에는 적합하지 않음
* ﻿﻿언제 사용: 사용자 설정을 저장하고 조회할 때.
* ﻿﻿왜 사용: 간단한 데이터 저장이 필요할 때 빠르고 효율적
* ﻿﻿어떻게 사용: @AppStorage 어노테이션과 함께 저장 키를 지정\
  `@AppStorage ("user_name") var userName: String = "Guest"`

사용 예시코드&#x20;

```swift
struct ContentView: View {
    @AppStorage ("user_name") var userName: String = "Guest"
    
    var body: some View {
        Text("환영합니다, \(userName)")
    }
}
```

## 7. @SceneStorage

* ﻿﻿정의: 앱의 다양한 씬 상태를 저장하고 복원
* ﻿장점: 상태 복원이 쉬움
* ﻿﻿단점: 복잡한 데이터 저장에는 적합하지 않음. (테이터 타입 제한, 로컬 저장이라 여 러 디바이스간의 상태 공유X)
* ﻿﻿언제 사용: 앱의 다양한 '장면'간의 데이터 공유시 사용
* ﻿﻿왜 사용: 사용자가 앱을 다시 열었을 때 이전 상태를 복원하기 위해.
* ﻿﻿어떻게 사용: @SceneStorage를 변수 앞에 붙여 사용
* ﻿﻿사용 예: 탭의 선택 상태를 기억하는 코드에서 사용

```swift
struct ContentView: View {
    @SceneStorage ("selectedTab") var selectedTab: String?
    var body: some View {
        TabView(selection: §selectedTab) {
            Text ("Tab 1")
                .tabItem {
                    Text ("Tab 1")
                ｝
                .tag("firstTab")
        
            Text ("Tab 2")
                .tabItem {
                    Text("Tab 2")
                }
                .tag ("secondTab" )
        }
    }
｝
```

참고로 이 예시에서, 탭의 선택 상태는 selectedTab 변수에 저장되고, 앱이 종료된 후 다시 실행될 때 이 상태를 복원

**@AppStorage, @scenestorage 공통점과 차이점**

* ﻿﻿공통점: 둘 다 앱의 상태를 저장하고 복원하는데 사용
* ﻿﻿차이점: @AppStorage는 앱 전체에 걸쳐 상태를 저장하고 복원하며, @SceneStorage는 특정 Scene에서만 국한된 상태를 저장

## 8. @Environment

* ﻿﻿정의: 시스템 환경 변수나 앱 설정을 View로 주입
* ﻿﻿장점: 전역 설정을 쉽게 접근할 수 있음
* ﻿﻿단점: 사용 가능한 키가 SwiftUI에 의해 제한됨.
* ﻿﻿언제 사용: 시스템 설정을 View에서 필요로 할 때.
* ﻿﻿왜 사용: 시스템 설정에 쉽고 효율적으로 접근하기 위해.
* ﻿﻿어떻게 사용: @Environment 어노테이션과 함께 특정 키를 사용\
  @Environment (l. locale) var locale

사용 예시코드&#x20;

```swift
struct ContentView: View {
    @Environment (\. locale) var locale
    
    var body: some View {
        Text("현재 로케일: 1(Locale)")
    }
}
```

@AppStorage, @Environment 공통점과 차이점

* 공통점: @AppStorage와 @Environment는 둘 다 설정 값을 저장하고 조회하는 데 사용
* 차이점: @AppStorage는 사용자 설정을 UserDefaults에 저장, @Environment는 시스템 환경 설정을 가져옴

## 9. @StateObject

* ﻿﻿정의: 소유권을 가지는 옵저버블 오브젝트를 저장(SwiftuI에서 참조 타입의 상태 객체를 안전하게 소유하고 관리)
* ﻿﻿장점: 상태 소유권(상태 객체를 안전하게 소유 및 관리), 데이터 공유(여러 뷰에서 공 유 가능)
* 단점: 단일 뷰에서만 소유 할 수 있음, 메모리관리(객체가 뷰 외부에서 생성되지 않으 면 메모리 누수의 위험있음)
* ﻿﻿언제 사용: 뷰와 뷰 계층에서 공유되어야 하는 상태가 있는 경우.
* ﻿﻿왜 사용: 데이터의 소유권과 생명주기를 관리하기 위해, 데이터 또는 상태를 뷰 계층 에 안전하게 공유하고 싶을때
* ﻿﻿어떻게 사용: @StateObject 어노테이션을 변수 앞에 붙여 사용
* ﻿﻿사용 예: viewModel을 뷰에서 직접 생성하고 관리 할때.
* ﻿﻿사용 예시코드 :

```swift
class Counter: ObservableObject {
    @Published var count = 0
}

struct ContentView: View {
    @StateObject var counter = Counter ()
    
    var body: some View {
        VStack {
            Text ('Count: \(counter. count)")
            Button ("Increment") {
                counter. count += 1
            }
        }
    }
}
```

@stateobject를 사용하여 Counter라는 ObservableObject를 ContentView 내에서 생성하고 관리하는 코드 예제

이 예에서 Counter는 상태를 발행하는 클래스이며, @Published 프로퍼티 래퍼를 사용하여 count 변수의 변화를 감지.

ContentView는 이 Counter 객체를 @StateObject로 선언하여 뷰가 소멸되어 다시 생성될 때에도 Counter

객체가 유지되게함

이렇게 하면 Counter의 상태가 ContentView에 안전하게 바인딩되고, "Increment" 버튼을 누르면 count 값이 증가하면서 UI가 자동으로 업데이트됨

## 10. @FetchRequest

* ﻿﻿정의: Core Data패치 요청의 결과를 바인딩함
* ﻿﻿장점: Core Data 통합이 매우 쉬움, 자동 업데이트(Core Data의 변경 사항 자동 반 영)
* ﻿﻿단점: Core Data에만 특화되어 있음(Only Core Data), 쿼리제한(복잡한 쿼리 수행 할 수 없음)
* ﻿﻿언제 사용: Core Data를 사용하여 데이터를 검색, 이를 뷰에 표시할 필요가 있을 때
* ﻿﻿왜 사용: Core Data 데이터를 쉽고 빠르게 가져오고 비를 업데이트하기 위해
* ﻿﻿어떻게 사용: @FetchRequest 어노테이션을 변수 앞에 붙여 사용
* ﻿﻿사용 예: Core Data의 엔터티 목록을 테이블 뷰에 표시할 때
* ﻿﻿사용 예시코드

<pre class="language-swift"><code class="lang-swift">import SwiftuI
import CoreData

struct ContentView: View {
<strong>    @FetchRequest (sortDescriptors: [NSSortDescriptor (keyPath: \Item. timestamp, ascending:
</strong>    animation: . default)
    private var items: FetchedResults&#x3C;Item>
    
<strong>    var body: some View {
</strong>        List {
        ForEach(items) { item in
            Text("Item at \(item.timestamp!, formatter: itemFormatter)")
        }
    }
}
</code></pre>

**다른 옵션과의 차이점**

* @Observedobject와의 차이점
  * @ObservedObject는 일반적인 ObservableObject를 바인딩할 때 사용되며, @FetchRequest는 Core Data 와 특화되어 있습니다.
* &#x20;@StateObject과 @FetchRequest의 공통점과 차이점
  * ﻿﻿공통점: 둘 다 데이터를 뷰에 바인딩하는 데 사용
  * ﻿﻿차이점: @StateObject은 일반적인 상태 관리에 사용, @FetchRequest는 Core Data와 특화됨

***

데이터의 소유와 범위

* ﻿﻿상태 관리(@State, @Binding, @observedobject, @Stateobject, @Environmentobject): 이들은 데이터의 상태를 뷰와 연결시키는 역할
* ﻿﻿데이터 저장(@Appstorage, @Scenestorage): 이 두 래퍼는 데이터를 지속적으로 저장하는 역할
* ﻿﻿시스템 정보 접근(@Environment, @FetchRequest): 이들은 앱의 실행 환경이나 외 부 데이터에 대한 접근을 담당

알림 메커니즘

* ﻿﻿자동 알림(@State, @Published, @observedobject, @Environmentobject, @StateObject): 이들은 값이 변경될 때 자동으로 뷰를 업데이트
* ﻿﻿명시적 알림(@Binding, @Environment, @FetchRequest, @AppStorage, @SceneStorage): 이들은 상태나 데이터 변경을 외부 요인(사용자 액션, 시스템 설정 등)에 의존하며, 뷰 업데이트를 명시적으로 요청할 수 있음

데이터의 생명주기

* ﻿﻿뷰 생명주기(@State, @Binding, @observedobject): 이 래퍼들은 뷰의 생명주기에 따라 데이터가 유지
* ﻿﻿앱 생명주기(@Appstorage, @SceneStorage, @Environmentobject, @StateObject): 이 래퍼들은 앱이나 씬(scene)의 생명주기 동안 데이터를 유지&#x20;

데이터 소스

* ﻿﻿내부 데이터(@State, @Binding, @observedobject, @Stateobject): 이들은 주 로 앱 내부에서 생성되거나 관리되는 데이터를 다룸
* ﻿﻿외부 데이터(@Environment, @FetchRequest, @AppStorage, @SceneStorage, @Environmentobject): 이들은 주로 앱 외부(시스템 설정, 파일, 네트워크 등)에서 가져오는 데이터를 다룸!

### Published의 사용

@Published 속성에 대한 $ 사용의 유무는 그 속성에 직접 접근할 것인지, 아니면 그 속성의 변경 사항을 관찰할 것인지에 따라 달라집니다.

* **With $**: @Published 속성의 Publisher에 접근할 때 사용합니다. 즉, viewModel.$name은 Published\<String>.Publisher 타입입니다. 이 Publisher는 값의 변화를 관찰(subscribe)하거나 반응할 때 사용됩니다.
* **Without $**: @Published 속성의 실제 값에 접근하거나 변경할 때 사용합니다. 즉, viewModel.name은 String 타입입니다.

출처

{% embed url="<https://m.blog.naver.com/codingbarbie/223223024066>" %}
