I'm building an app using SwiftUI and would like a way to convert a Binding<Value?>
to a Binding<Value
>.
In my app I have an AvatarView
which knows how to render an image for a particular user.
struct AvatarView: View { @Binding var userData: UserData ... }
My app holds a ContentView
that owns two bindings: a dictionary of users by id, and the id of the user whose avatar we should be showing.
struct ContentView: View { @State var userById: Dictionary<Int, UserData> @State var activeUserId: Int var body: some View { AvatarView(userData: $userById[activeUserId]) } }
Problem: the above code doesn't combine because $userById[activeUserId]
is of type Binding<UserData?>
and AvatarView
takes in a Binding<UserData>
.
Things I tried...
$userById[activeUserId]!
doesn't work because it's trying to unwrap a Binding<UserData?>
. You can only unwrap an Optional
, not a Binding<Optional>
.
$(userById[activeUserId]!)
doesn't work for reasons that I don't yet understand, but I think something about $
is resolved at compile time so you can't seem to prefix arbitrary expressions with $
.
An optional String cannot be used in place of an actual String . To use the wrapped value inside an optional, you have to unwrap it. The simplest way to unwrap an optional is to add a ! after the optional name. This is called "force unwrapping".
Even though Swift isn't sure the conversion will work, you can see the code is safe so you can force unwrap the result by writing ! after Int(str) , like this: let num = Int(str)! Swift will immediately unwrap the optional and make num a regular Int rather than an Int? .
Optional Binding is used to safely unwrap the optional value. Step one: We assign our optional value to temporary constant & variable. Step Two: If the optional variable contains a value it will be assigned to our temporary variable.
You can use this initialiser, which seems to handle this exact case - converting Binding<T?>
to Binding<T>?
:
var body: some View { AvatarView(userData: Binding($userById[activeUserId])!) }
I have used !
to force unwrap, just like in your attempts, but you could unwrap the nil
however you want. The expression Binding($userById[activeUserId])
is of type Binding<UserData>?
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With