SwiftUIを学び始めると、コードの中で「$text
」や「$isOn
」のような、$
マークが付いた変数を見かけることがあります。最初は「これって何?」と戸惑うかもしれませんが、実はSwiftUIの核心的な機能の一つなんです。
今回は、この$変数
について、初心者の方にもわかりやすく解説していきます。
$変数
の正体:それは「Binding」です
$変数
の正体は**Binding(バインディング)**と呼ばれるものです。Bindingを一言で表すと:
「値を読み取ることも、書き換えることもできる双方向の接続」
普通の変数が「値そのもの」を表すのに対し、$変数
は「値への接続」を表します。
身近な例で理解してみよう
まずは、実際のコードを見てみましょう:
struct ContentView: View {
@State private var userName = ""
var body: some View {
VStack {
TextField("名前を入力", text: $userName)
Text("こんにちは、\(userName)さん!")
}
}
}
この例では:
userName
:文字列の値そのもの$userName
:その値への双方向の接続
TextField
に$userName
を渡すことで、TextFieldは:
userName
の現在の値を表示できる(読み取り)- ユーザーが入力した内容で
userName
を更新できる(書き込み)
なぜBindingが必要なのか?
もし普通の変数userName
をTextFieldに渡したらどうなるでしょうか?
// これは動きません
TextField("名前を入力", text: userName) // ❌
この場合、TextFieldは値を読み取ることはできますが、ユーザーが文字を入力しても元の変数を更新することができません。つまり、一方通行の関係になってしまいます。
Bindingを使うことで、双方向のデータフローが実現されるのです。
プロパティラッパーと$
の関係
技術的な話になりますが、$
はプロパティラッパーの機能を利用しています。
@State private var isOn = false
@State
はプロパティラッパーと呼ばれるもので、変数に特別な機能を追加します。そして、$isOn
は@State
のprojectedValue
にアクセスする構文です。
よく使われるプロパティラッパーとBinding
プロパティラッパー | 用途 | Bindingの例 |
---|---|---|
@State | ビュー内の状態管理 | $text , $isOn |
@StateObject | オブジェクトの状態管理 | $model.property |
@ObservedObject | 外部オブジェクトの観察 | $viewModel.data |
@AppStorage | UserDefaults連携 | $settings |
@FocusState | フォーカス状態管理 | $isFocused |
実際の使用例
1. Toggle(スイッチ)
struct SettingsView: View {
@State private var isNotificationOn = true
var body: some View {
Toggle("通知を受け取る", isOn: $isNotificationOn)
}
}
2. Slider(スライダー)
struct VolumeView: View {
@State private var volume: Double = 50
var body: some View {
VStack {
Slider(value: $volume, in: 0...100)
Text("音量: \(Int(volume))")
}
}
}
3. Picker(選択肢)
struct ColorPickerView: View {
@State private var selectedColor = "赤"
let colors = ["赤", "青", "緑"]
var body: some View {
Picker("色を選択", selection: $selectedColor) {
ForEach(colors, id: \.self) { color in
Text(color)
}
}
}
}
複雑な例:カスタムビューとBinding
子ビューにBindingを渡すこともできます:
struct CounterView: View {
@Binding var count: Int
var body: some View {
HStack {
Button("-") { count -= 1 }
Text("\(count)")
Button("+") { count += 1 }
}
}
}
struct ParentView: View {
@State private var number = 0
var body: some View {
VStack {
Text("現在の数: \(number)")
CounterView(count: $number) // Bindingを渡す
}
}
}
この例では、CounterView
が親ビューのnumber
を直接変更できます。
よくある間違いと対処法
間違い1:BindingとStateの混同
// ❌ 間違い
@Binding var text: String = "初期値" // Bindingに初期値は設定できない
// ✅ 正しい
@Binding var text: String // 親から値を受け取る
間違い2:$を付け忘れ
// ❌ 間違い
TextField("入力", text: text)
// ✅ 正しい
TextField("入力", text: $text)
間違い3:不要な$を付ける
// ❌ 間違い
Text($text) // Textは値を表示するだけなので$は不要
// ✅ 正しい
Text(text)
まとめ
$変数
は、SwiftUIでデータを双方向にやり取りするための重要な仕組みです。
覚えておきたいポイント:
変数
:値そのもの$変数
:値への双方向の接続(Binding)- ユーザー入力を受け取るコンポーネント(TextField、Toggle等)にはBindingを渡す
- 値を表示するだけのコンポーネント(Text等)には普通の変数を渡す
最初は慣れないかもしれませんが、使っているうちに「なるほど、これは便利だ!」と感じるはずです。SwiftUIの魅力の一つでもあるので、ぜひ積極的に活用してみてください。