import SwiftUI
// MARK: - State and Binding
struct CounterView: View {
@State private var count = 0
var body: some View {
VStack(spacing: 20) {
Text("Count: \(count)")
.font(.largeTitle)
CounterControls(count: $count)
}
}
}
struct CounterControls: View {
@Binding var count: Int
var body: some View {
HStack(spacing: 20) {
Button("-") { count -= 1 }
Button("+") { count += 1 }
}
.buttonStyle(.bordered)
}
}
// MARK: - ObservableObject and StateObject
class UserSettings: ObservableObject {
@Published var username = ""
@Published var isDarkMode = false
@Published var notificationsEnabled = true
static let shared = UserSettings()
}
struct SettingsView: View {
@StateObject private var settings = UserSettings()
var body: some View {
Form {
TextField("Username", text: $settings.username)
Toggle("Dark Mode", isOn: $settings.isDarkMode)
Toggle("Notifications", isOn: $settings.notificationsEnabled)
}
.environmentObject(settings)
}
}
// MARK: - Environment and EnvironmentObject
struct ProfileView: View {
@EnvironmentObject var settings: UserSettings
@Environment(\.colorScheme) var colorScheme
@Environment(\.dismiss) var dismiss
var body: some View {
VStack {
Text("Hello, \(settings.username)")
Text("Current theme: \(colorScheme == .dark ? "Dark" : "Light")")
Button("Close") {
dismiss()
}
}
}
}
// MARK: - AppStorage
struct PreferencesView: View {
@AppStorage("fontSize") private var fontSize = 16.0
@AppStorage("showImages") private var showImages = true
@AppStorage("lastLoginDate") private var lastLoginDate = Date()
var body: some View {
Form {
Slider(value: $fontSize, in: 12...24) {
Text("Font Size: \(Int(fontSize))")
}
Toggle("Show Images", isOn: $showImages)
Text("Last login: \(lastLoginDate.formatted())")
}
}
}
SwiftUI property wrappers manage state and data flow declaratively. @State creates mutable state owned by a view for simple values. @Binding creates two-way connections to pass state down the hierarchy without ownership. @ObservedObject watches external ObservableObject instances for changes. @StateObject creates and owns ObservableObject instances with proper lifecycle. @EnvironmentObject provides dependency injection across the view tree. @Environment accesses system values like color scheme or size category. @AppStorage persists simple values to UserDefaults. @Published marks properties that trigger view updates. Understanding which wrapper to use prevents memory leaks and ensures correct data flow.