TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

How to return mulitple views using return statement in SwiftUI?

Forums > SwiftUI

Hi Developers.

I want to return multiple Views using return statement. e.g


struct ContentView: View {
    @State private var isConditionMet = false
    var body: some View {

        let backgroundColor:Color = isConditionMet ? .yellow : .orange

            return VStack {
                Text("Conditional Background Color")
                    .font(.title)
                    .padding()

                Button(action: {
                    // Toggle the condition
                    self.isConditionMet.toggle()
                }) {
                    Text("Toggle Condition")
                        .padding()
                        .background(Color.blue)
                        .foregroundColor(.white)
                        .cornerRadius(8)
                }

                // Background color determined by the condition
                Rectangle()
                    .fill(backgroundColor)
                    .frame(width: 200, height: 200)
                    .padding()
            }
        Color.green

        }
}

I want to have some condition based on state. before rendering. I get warning saying color.green will not be reached. which is understandable, but then how is it accepting it in normal closure?

   

Ternary operators to the rescue

struct ContentView: View {
    @State private var isConditionMet = false
    var body: some View {
        VStack {
            Text("Conditional Background Color")
                .font(.title)
                .padding()

            Button(action: {
                // Toggle the condition
                self.isConditionMet.toggle()
            }) {
                Text("Toggle Condition")
                    .padding()
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .cornerRadius(8)
            }

            // Background color determined by the condition
            Rectangle()
                .fill(isConditionMet ? .yellow : .orange) // move condition here
                .frame(width: 200, height: 200)
                .padding()
        }
        Color.green
    }
}

or move Color.green inside the View like so:

struct ContentView: View {
    @State private var isConditionMet = false
    var body: some View {

        let backgroundColor:Color = isConditionMet ? .yellow : .orange

        return VStack {
            Text("Conditional Background Color")
                .font(.title)
                .padding()

            Button(action: {
                // Toggle the condition
                self.isConditionMet.toggle()
            }) {
                Text("Toggle Condition")
                    .padding()
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .cornerRadius(8)
            }

            // Background color determined by the condition
            Rectangle()
                .fill(backgroundColor)
                .frame(width: 200, height: 200)
                .padding()

            Color.green // Move inside VStack
        }
    }
}

   

@ygeras adding color to VStack would break the strucutre I am looking for. Color.green and VStack content should be 50-50.

also about soln #1, terneray operator is good approach if conditions are simple, but in case of complex conditions/calculations, it might not be feasible.

I am trying to simulate a way where in i can have some calculations based on current views State. I come from React so in react you have certain calculations you can do based on states before return statement. I am trying to achive something similar.

I am able to do that with just a single view, but it doesn't work with returning mulitple views

   

I am not familiar with React, but most programmig languages stop/end executing code after "return" keyword. In your code you return a view and then declare another view... so XCode will warn you, that it will never execute that line. As for the view to make it take proportional screen, there are many ways to do that, as well as make necessary calculations. Narrow down your question to the parts you would like to achieve so community will be able to understand more clearly your task at hand and help :)

as another approach try to make custom view that can handle more views. Break down view to pass to another view, make calculations etc... there many ways to handle the same...

struct ContentView: View {
    @State private var isConditionMet = false
    var body: some View {

        let backgroundColor:Color = isConditionMet ? .yellow : .orange

        MultipleView {
            Text("Conditional Background Color")
                .font(.title)
                .padding()

            Button(action: {
                // Toggle the condition
                self.isConditionMet.toggle()
            }) {
                Text("Toggle Condition")
                    .padding()
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .cornerRadius(8)
            }

            // Background color determined by the condition
            Rectangle()
                .fill(backgroundColor)
                .frame(width: 200, height: 200)
                .padding()
        } view2: {
            Color.green
        }
    }
}

struct MultipleView<View1: View, View2: View>: View {
    @ViewBuilder var view1: () -> View1
    @ViewBuilder var view2: () -> View2

    var body: some View {
        VStack {
            view1()
            view2()
        }
        .border(Color.red, width: 3)
    }
}

Even simple removing "return" keyword makes your code work.

   

Even simple removing "return" keyword makes your code work.

@ygeras This is something I was looking for! I can have complex conditions on top and return multiple views.

can you help me understand how is it returning views without return statement and with logic above it?

and Thanks for the solution!

   

In simple words SwiftUI revolves around structs that conform to View protocol. The protocol requires you to have property var body that has to return some View. Return is implicit when you have one statement, but if you place two structs or more and use return before code will run only for that struct and not others.

Like you can see if you run this code:

struct ContentView: View {
    var body: some View {

        Text("Hello, world!")

        return
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)

        Text("Hello, world!")
        Text("Hello, world!")
    }
}

you will notice that the text structs have the same warnings that you have. This is very simplified example and explanation. There are much more happening behind the scenes, that is hidden from us :)

   

Hacking with Swift is sponsored by Blaze.

SPONSORED Still waiting on your CI build? Speed it up ~3x with Blaze - change one line, pay less, keep your existing GitHub workflows. First 25 HWS readers to use code HACKING at checkout get 50% off the first year. Try it now for free!

Reserve your spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.