History
Loading...
Loading...
September 25, 2025
PreferenceKey to pass data upstream from child views to parent views when @Binding isn't suitable. Perfect for collecting scroll positions, view dimensions, or selection states from deeply nested components without tight coupling.This pattern creates a type-safe communication channel where child views can report their state or measurements to parent views without requiring direct bindings or callback closures. The PreferenceKey protocol ensures consistent data handling and automatic view updates.
struct ViewSizeKey: PreferenceKey {
static var defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
value = nextValue()
}
}
struct ContentView: View {
@State private var childSize: CGSize = .zero
var body: some View {
VStack {
Text("Child size: \(Int(childSize.width))x\(Int(childSize.height))")
ChildView()
.background(
GeometryReader { geometry in
Color.clear
.preference(key: ViewSizeKey.self, value: geometry.size)
}
)
}
.onPreferenceChange(ViewSizeKey.self) { size in
childSize = size
}
}
}PreferenceKeys maintain SwiftUI's declarative nature while solving the reverse data flow problem. They're more performant than callback closures, automatically handle view lifecycle, and integrate seamlessly with SwiftUI's preference system for clean, maintainable code architecture.