@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 updated3. 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
| Aspect | Detail |
|---|---|
| Mục đích | Two-way binding giữa Views |
| Tạo từ | $stateVariable |
| Nhận | @Binding var property |
| Constant | .constant(value) |
| Custom | Binding(get:set:) |
Last updated on