[SwiftUI]データバインディングについて(@State, @Binding, ObservableObject)

# 目次

1. [データバインディングとは](#データバインディングとは)
2. [@Stateについて](#`@State`について)
3. [@Bindingについて](#`@Binding`について)
4. [ObservableObjectについて](#ObservableObjectについて)
5. [まとめ](#まとめ)
6. [さいごに](#さいごに)


# データバインディングとは

データバインディングとは、UIとデータの間での双方向の同期を可能にする仕組みです。
ビュー内での状態変更が自動的にUIに反映され、逆にUI上での操作もデータの状態に反映されます。

# `@State`について

`@State`は、ローカルな状態を管理するためのプロパティラッパーです。
ビュー内で状態を保持し、変更する際にUIが自動的に再描画されます。

# `@State`の使い方

```swift
struct CounterView: View {

    // カウンターの値を管理する状態。初期値は0
    @State private var count = 0

    var body: some View {
        VStack {
            // 現在のカウントを表示するテキスト
            Text("Count: \(count)")
            Button("Increment") {
                // ボタンを押すとカウントを+1
                count += 1
            }
        }
    }
}
```

![RPReplay_Final1707205758-2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3530812/9d77e78d-9b67-e6a5-0008-62753fcdd90f.gif)


# `@Binding`について

`@Binding`は、他のViewから状態を共有するためのプロパティラッパーです。
親ビューから子ビューにデータを渡し、双方向の通信を可能にします。
データをViewから直接操作します。

# `@Binding`の使い方

```swift
struct ChildView: View {
    // 親ビューから渡されるカウンターの値を受け取るBinding
    @Binding var count: Int
    
    var body: some View {
        Button("Increment") {
            // ボタンを押すとカウントを+1
            count += 1
        }
    }
}

struct ParentView: View {
    // このビュー内で管理されるローカルなカウンターの値を定義
    @State private var count = 0
    
    var body: some View {
        VStack {
            Text("Count: \(count)")

            // ChildViewに親ビューのカウンターの値をバインドして渡す
            ChildView(count: $count)
        }
    }
}
```

# `ObservableObject`について

`ObservableObject`は、データの変更を監視し、その変更をUIに反映させるためのプロトコルです。主にViewModelで使用され、アプリケーションの状態やビジネスロジックを管理します。
`ObservableObject`を準拠するクラスや構造体では、`@Published`プロパティラッパーを使用して、プロパティの変更を自動的に通知します。これにより、プロパティの値が変更されると、それに関連するビューが自動的に再描画されます。

# `ObservableObject`の使い方

```swift
class MyViewModel: ObservableObject {
    // ユーザー名を管理するObservableObject。@Publishedを使ってプロパティの変更を自動的に通知
    @Published var username: String = ""
}

struct ContentView: View {
    // MyViewModelを監視し、その状態の変化を検知する
    @ObservedObject var viewModel = MyViewModel()
    
    var body: some View {

        // ユーザー名を入力するテキストフィールド。viewModelのusernameをバインドしている
        TextField("Enter username", text: $viewModel.username)
            .padding()
            // テキストが変更されるたびにコンソールに出力
            .onChange(of: viewModel.username) { newValue in
                print("New username: \(newValue)")
            }
    }
}
```
![画面収録-2024-02-06-16.46.12.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3530812/d0a596ce-b210-ea4c-2226-fce1c51a9a68.gif)


# まとめ

データバインディングは、UIとデータの間での双方向の同期を実現します。
`@State`、`@Binding`、`ObservableObject`などのプロパティラッパーを使用することで、状態の管理やデータの共有を容易にします。

`@State`: ビュー内でローカルな状態を管理し、UIの変更を自動的に反映します。
`@Binding`: 親ビューから子ビューにデータを渡し、双方向の通信を実現します。
`ObservableObject`: ViewModelで使用され、データの変更を監視し、UIに反映させます。

iOS17以降からはObservationという新たな状態監視のFrameworkが使用できるみたいです！
詳しくは[こちら](https://qiita.com/k_awoki/items/a71d8e833f99fedda7c5)の記事に書いてあります！

# さいごに

弊社では、経験の有無を問わず採用を行っています。
興味のある方は是非カジュアル面談しましょう！
https://jambo-support.com/recruit_engineer/

## 参考文献

https://qiita.com/k_awoki/items/a71d8e833f99fedda7c5