3

This is basically my code I have:

var myString: String?

var body: some View {
  NavigationView {
    if myString != nil {
      CustomView(text: myString ?? "")
    }
  }
}

If I try without adding the ?? "" part, it doesn't work, says Value of optional type 'String?' must be unwrapped to a value of type 'String'. If I add it in as shown above, it seems to work, but why do I need to have a default empty string value if that's never going to be the case? (Since it will only reach that code if myString is not nil) Is there a way I can make this code more cleaner?

pizzae
  • 2,815
  • 6
  • 26
  • 45

2 Answers2

3

You need to use optional binding to unwrap the safely optional variable. However simply using that inside body will result in a compiler error because not all control flow (including if let) is allowed inside the body of the view, so you'll need to wrap it in another computed property.

struct MyView: View {

    var myString: String?

    var body: some View {
      NavigationView {
        innerView
      }
    }

    var innerView: some View {
        if let myString = myString {
            return AnyView(CustomView(text: myString))
        } else {
            return AnyView(EmptyView())
        }
    }
}

Or you can simplify that using Optional.map.

struct MyView: View {
    var myString: String?

    var body: some View {
      NavigationView {
        myString.map { CustomView(text: $0) }
      }
    }
}
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
1
if let myString = myString {
  CustomView(text: myString)
}

This is one of the ways to safely unwrap an optional, but as it was pointed out it won't work inside a view builder block. Instead you can use map to keep it simple.

var myString: String?

var body: some View {
  NavigationView {
    myString.map { CustomView(text: $0) }
  }
}
EmilioPelaez
  • 18,758
  • 6
  • 46
  • 50
  • 1
    And that results in a compiler error `Closure containing control flow statement cannot be used with function builder 'ViewBuilder'`. See [How to have a dynamic list of views using SwiftUI](https://stackoverflow.com/questions/56645647/how-to-have-a-dynamic-list-of-views-using-swiftui). – Dávid Pásztor May 08 '20 at 15:45
  • @pizzae no, that piece of code inside your `body` doesn't compile – Dávid Pásztor May 08 '20 at 15:50
  • @pizzae I updated my answer to work with SwiftUI view builders – EmilioPelaez May 08 '20 at 15:53