Jak mogę rozpakować opcjonalną wartość w powiązaniu w Swift?

9

Tworzę aplikację za pomocą SwiftUI i chciałbym sposób przekonwertować Binding<Value?>na Binding<Value>.

W mojej aplikacji mam taki, AvatarViewktóry wie, jak renderować obraz dla konkretnego użytkownika.

struct AvatarView: View {
  @Binding var userData: UserData

  ...
}

Moja aplikacja zawiera ContentViewdwa powiązania: słownik użytkowników według identyfikatora i identyfikator użytkownika, którego awatar powinniśmy wyświetlać.

struct ContentView: View {
  @State var userById: Dictionary<Int, UserData>
  @State var activeUserId: Int

  var body: some View {
    AvatarView(userData: $userById[activeUserId])
  }
}

Problem: powyższy kod nie łączy się, ponieważ $userById[activeUserId]jest typu Binding<UserData?>i AvatarViewprzyjmuje Binding<UserData>.

Rzeczy, których próbowałem ...

  • $userById[activeUserId]!nie działa, ponieważ próbuje rozpakować plik Binding<UserData?>. Możesz tylko rozpakować Optional, a nie Binding<Optional>.

  • $(userById[activeUserId]!)nie działa z powodów, których jeszcze nie rozumiem, ale myślę, że coś $zostało rozwiązane w czasie kompilacji, więc nie możesz poprzedzać dowolnych wyrażeń $.

rjkaplan
źródło
Próbowałeś $userById[activeUserId] as! Binding<UserData>?
Kamran
Dzieki za sugestie! Myślę, że to prawdopodobnie działałoby dobrze, ale wolałbym nie robić niebezpiecznej obsady. Gdy próbuję, pojawia się ostrzeżenie o kompilacji z napisem „Rzuć z Binding <UserData?> Na niepowiązany typ Binding <UserData>”
rjkaplan

Odpowiedzi:

10

Możesz użyć tego inicjalizatora , który wydaje się obsługiwać dokładnie ten przypadek - konwertując Binding<T?>na Binding<T>?:

var body: some View {
    AvatarView(userData: Binding($userById[activeUserId])!)
}

Kiedyś !wymuszałem rozpakowywanie, tak jak przy twoich próbach, ale możesz rozpakowywać tak nil, jak chcesz. Wyrażenie Binding($userById[activeUserId])jest typu Binding<UserData>?.

Zamiatarka
źródło