Search code examples
swiftswiftuiviewconditional-statementsclosures

SwiftUI - alternative to if let with a conditional closure


I'm trying to implement the following in SwiftUI:

struct PersonView: View {

    @State private var age: Int? = 0

    var body: some View {
        VStack {
            Text("Just a test")
            if let self.age > 0 {
                Text("Display Age: \(age)")
            } else {
                Text("Age must be greater than 0!")
            }
        }
    }
}

But, in SwiftUI, if let results in the following error:

Closure containing control flow statement cannot be used with function builder 'ViewBuilder'

So after researching this topic, I came across a recommendation to use .map to unwrap the age optional. Thus, I've modified to code within the VStack as follows:

Text("Just a test")
self.age.map {elem in
    if elem > 0 {
        Text("Display Age: \(elem)")
    } else {
        Text("Age must be greater than 0!")
    }
}

Including a conditional within the .map closure, however, results in the following errors at the line calling the VStack:

' (ViewBuilder.Type) -> (C0, C1) -> TupleView<(C0, C1)>' requires that '()' conform to 'View'

Type '()' does not conform to protocol 'View'

Any suggestions for how to get past the 2nd set of errors? Or, is there another approach for unwrapping optionals and evaluating them in SwiftUI? Really like SwiftUI but can't believe that unwrapping optionals has been a headache!


Solution

  • For such cases I prefer the following approach

    struct PersonView: View {
    
        @State private var age: Int? = 0
    
        var body: some View {
            VStack {
                Text("Just a test")
                AgeText
            }
        }
    
        private var AgeText: some View {
            if let age = self.age, age > 0 {
                return Text("Display Age: \(age)")
            } else {
                return Text("Age must be greater than 0!")
            }
        }
    }