Using The .focusedValue Modifier and @FocusedBinding Property Wrapper In SwiftUI
Daily Coding Tip 041
This is a new way to pass data between Views. Instead of having an
ObservableObject, we save data using a
In the following example,
DisplayTextView is able to show the text you type into
TextFieldView, despite the fact that a
String constant is not passed between the Views.
The magic here is enabled by the structure and extension at the bottom.
FocusedValueKey protocol requires that conforming structures have a
typealias for the value they store.
Once you have a structure that defines a
typealias for your key, you’ll need to define a getter and setter for that value. This extension of
\.text as the key that we will use to read and write the value. Notice that the getter and setter both use the
FocusedTextKey type as a subscript for
FocusedValues. Now we just need to write a value to the key in
TextFieldView, and then we need to read from it in
.focusedValue(\.text, $text) modifier on the
TextField saves the value to the key.
@FocusedBinding(\.text) var text: String? property in
DisplayTextView subscribes it to changes in the associated value. Notice that it is an optional, because the value does not have to be set. As Apple’s official documentation says, “Unlike
FocusedValuesHostKey has no default value requirement, because the default value for a key is always
nil.” I assume the original name was
FocusedValuesHostKey, because the documentation still mentions this despite the fact it no longer exists.
In other words, you can set up a key without giving it a value, and your code will still run.
When you do set up a value, you will need to unwrap it as I did using the nil coalescing operator ‘??’.
The next question you might have is why these values would be needed. After all, they seem to be global, at least in the context of a single window. We wouldn’t want to keep all our data at this scope, and having a lot of them might make it hard to debug. A more complex example by an Apple Frameworks Engineer on the Apple Developer Forums shows an interesting use case. When a Mac app has separate commands, such as Shift, Cmd + D in that example, you may still want to access data in the app despite the fact that the commands are at the
Now you can!