Introduction
In SwiftUI, data generally flows downwards, meaning data is passed from parent views to child views. However, there are situations where you may want to pass data in the opposite direction—from a child view to a parent view.
SwiftUI’s PreferenceKey
protocol is a powerful solution for these cases. PreferenceKey
enables data to travel up the view hierarchy, allowing parent views to access values defined in their child views.
Creating a Custom PreferenceKey
To create a PreferenceKey
, start by defining a new struct that conforms to the PreferenceKey
protocol. This struct must have a defaultValue
and a reduce
function to aggregate multiple values.
struct MyPreferenceKey: PreferenceKey {
static var defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value += nextValue()
}
}
In this example, MyPreferenceKey
has a CGFloat
value, with a defaultValue
set to 0, and the reduce
function aggregates values by adding them up.
Applying the PreferenceKey
to a View
After creating a PreferenceKey
, apply it to a view using the preference
modifier. This allows you to specify a value for the PreferenceKey
within the child view.
Text("Hello, SwiftUI!")
.background(GeometryReader { geometry in
Color.clear.preference(key: MyPreferenceKey.self, value: geometry.size.height)
})
In this example, a GeometryReader
calculates the height of a Text
view, which is then stored as a PreferenceKey
value using the preference
modifier.
Reading a PreferenceKey
Value
To access a PreferenceKey
value, use the onPreferenceChange
modifier in the parent view. This allows you to respond to changes in the preference value.
VStack {
Text("Hello, SwiftUI!")
.background(GeometryReader { geometry in
Color.clear.preference(key: MyPreferenceKey.self, value: geometry.size.height)
})
}
.onPreferenceChange(MyPreferenceKey.self) { value in
print("Height of Text view: \(value)")
}
In this example, onPreferenceChange
monitors changes in MyPreferenceKey
and prints the height of the Text
view whenever it changes.
Be the first to comment