5

(Swift 5, SwiftUI) If I have the following code for a VStack:

struct ContentView: View {

var body: some View {

    ScrollView {
        VStack(alignment: .leading) {

                //Inside of VStack

        }.padding()
        .padding(.bottom, keyboard.currentHeight)
        .edgesIgnoringSafeArea(.bottom)
        .animation(.easeOut(duration: 0.16))
    }
}
}

How can I dynamically add Text()s to the VStack through a function and update the ScrollView height accordingly?

The function (is called by a button press):

func add() -> Void {
    //Adds a Text() element to the VStack. The content of the Text() is received from an API 
    //call, so it can't be hardcoded.
}

I'm looking for a simple way to add Text() elements to my VStack. I've extensively searched for the problem on Google but found nothing similar to this trivial problem. Any help would be appreciated.

aryanm
  • 1,183
  • 14
  • 26
  • This is related: https://stackoverflow.com/questions/61895745/in-swiftui-is-it-possible-to-add-a-new-view-onto-the-screen-with-a-button/61897586#61897586. In a nutshell, you don't add a View, but rather modify the state, and the View reacts to it. – New Dev May 28 '20 at 03:34

1 Answers1

6

Here is a demo of possible solution. Tested with Xcode 11.4

struct ContentView: View {
    @State private var texts: [String] = [] // storage for results
    var body: some View {

        ScrollView {
            VStack(alignment: .leading) {
                ForEach(texts, id: \.self) { text in // show received results
                    Text(text)
                }
            }.frame(maxWidth: .infinity)  // << important !!
            .padding()
                .padding(.bottom, keyboard.currentHeight)
                .edgesIgnoringSafeArea(.bottom)
                .animation(.easeOut(duration: 0.16))
        }
    }

    func add() -> Void {
        // store result string (must be on main queue)
        self.texts.append("result")
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • Your answer has helped me a lot. However, is it possible for me to use multiple Text()s in the ForEach loop? When I try it, I get an error saying "Type '()' cannot conform to 'View'; only struct/enum/class types can conform to protocols". – aryanm May 28 '20 at 07:18
  • 1
    @ElectroMonkey, what do you mean by "multiple Text"? ForEach already creates multiple Text, one per data in integrating array, so once you add new string into array, new Text will be created by ForEach. – Asperi May 28 '20 at 07:47
  • @Asperi can u check this https://stackoverflow.com/questions/68325402/vstack-and-hstack-alignment-and-what-is-the-behaviour-of-subviews – karthikeyan Jul 10 '21 at 09:54
  • Place the Texts into a container like a Stack, and then return the container as the cell's View. – Leslie Godwin Apr 30 '23 at 06:50