Skip to Content

@Binding trong SwiftUI

1. Giới thiệu

@Binding tạo two-way connection giữa parent và child view.

struct ParentView: View { @State private var isOn = false var body: some View { ChildView(isOn: $isOn) // Pass binding } } struct ChildView: View { @Binding var isOn: Bool // Receive binding var body: some View { Toggle("Toggle", isOn: $isOn) } }

2. Cách hoạt động

ParentView (@State) ↓ $isOn (Binding) ChildView (@Binding) ↓ thay đổi ParentView updated

3. Ví dụ thực tế

Custom Toggle

struct CustomToggle: View { @Binding var isOn: Bool var body: some View { Button { isOn.toggle() } label: { Image(systemName: isOn ? "checkmark.circle.fill" : "circle") .foregroundColor(isOn ? .green : .gray) .font(.title) } } } // Usage struct ContentView: View { @State private var option1 = false @State private var option2 = true var body: some View { VStack { HStack { Text("Option 1") Spacer() CustomToggle(isOn: $option1) } HStack { Text("Option 2") Spacer() CustomToggle(isOn: $option2) } } .padding() } }

Rating View

struct RatingView: View { @Binding var rating: Int let maxRating: Int = 5 var body: some View { HStack { ForEach(1...maxRating, id: \.self) { star in Image(systemName: star <= rating ? "star.fill" : "star") .foregroundColor(.yellow) .onTapGesture { rating = star } } } } } // Usage struct ReviewForm: View { @State private var rating = 3 var body: some View { VStack { Text("Rate this product") RatingView(rating: $rating) Text("Your rating: \(rating)/5") } } }

Form Fields

struct FormField: View { let label: String @Binding var text: String var placeholder: String = "" var body: some View { VStack(alignment: .leading, spacing: 4) { Text(label) .font(.caption) .foregroundColor(.gray) TextField(placeholder, text: $text) .textFieldStyle(.roundedBorder) } } } // Usage struct SignUpForm: View { @State private var name = "" @State private var email = "" @State private var password = "" var body: some View { VStack(spacing: 16) { FormField(label: "Name", text: $name, placeholder: "Enter name") FormField(label: "Email", text: $email, placeholder: "Enter email") FormField(label: "Password", text: $password) } .padding() } }

4. Constant Binding

Dùng cho preview hoặc testing.

// Không thể thay đổi RatingView(rating: .constant(4)) // Trong Preview #Preview { CustomToggle(isOn: .constant(true)) }

5. Computed Binding

struct ContentView: View { @State private var celsius: Double = 25 var fahrenheit: Binding<Double> { Binding( get: { celsius * 9/5 + 32 }, set: { celsius = ($0 - 32) * 5/9 } ) } var body: some View { VStack { Slider(value: $celsius, in: -40...100) Text("Celsius: \(celsius, specifier: "%.1f")°") Slider(value: fahrenheit, in: -40...212) Text("Fahrenheit: \(fahrenheit.wrappedValue, specifier: "%.1f")°") } .padding() } }

6. Sheet với Binding

struct ContentView: View { @State private var showSheet = false @State private var selectedColor = Color.blue var body: some View { VStack { Circle() .fill(selectedColor) .frame(width: 100, height: 100) Button("Choose Color") { showSheet = true } } .sheet(isPresented: $showSheet) { ColorPickerSheet(selectedColor: $selectedColor) } } } struct ColorPickerSheet: View { @Environment(\.dismiss) var dismiss @Binding var selectedColor: Color let colors: [Color] = [.red, .blue, .green, .orange, .purple] var body: some View { VStack { Text("Choose a color") .font(.headline) HStack { ForEach(colors, id: \.self) { color in Circle() .fill(color) .frame(width: 50, height: 50) .overlay( Circle() .stroke(selectedColor == color ? .black : .clear, lineWidth: 3) ) .onTapGesture { selectedColor = color dismiss() } } } } .padding() } }

7. Array Item Binding

struct TodoApp: View { @State private var todos = [ Todo(title: "Buy groceries", isComplete: false), Todo(title: "Call mom", isComplete: true) ] var body: some View { List { ForEach($todos) { $todo in HStack { Toggle("", isOn: $todo.isComplete) .labelsHidden() Text(todo.title) .strikethrough(todo.isComplete) } } } } } struct Todo: Identifiable { let id = UUID() var title: String var isComplete: Bool }

📝 Tóm tắt

AspectDetail
Mục đíchTwo-way binding giữa Views
Tạo từ$stateVariable
Nhận@Binding var property
Constant.constant(value)
CustomBinding(get:set:)
Last updated on