3

Every time I Tap the button I would like a new cardView to appear. I am wondering if this is possible in swiftUI and if so what action I would need to do it. It would be even better if I am able to pass some parameters in to the cardView struct but any help would be great!


struct ContentView: View {
    var body: some View {
        ZStack {
            VStack {
                TextButton(action: {print("Button tapped")}, text: "new card")
                CardView()
            }
        }
    }
}

struct CardView: View {
    var body: some View {
        ZStack {
            Rectangle()
                .fill(Color(#colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)))
                .frame(width: 100, height: 100 * 1.618)
                .cornerRadius(16)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.1), radius: 1, x: 0, y: 1)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.2), radius: 10, x: 0, y: 10)

            VStack {
                Text("Card")
                    .font(.system(size: 10) )
                    .foregroundColor(.white)
                    .bold()
            }
        }
    }
}


struct TextButton: View {
    let action: () -> Void
    let text: String

    var body: some View {
        Button(action: action, label: {
            Text(text)
                .padding(.horizontal, 16)
                .padding(.vertical, 16)
                .foregroundColor(.white)
                .background(Color.blue)
                .cornerRadius(.infinity)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.1), radius: 1, x: 0, y: 1)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.2), radius: 10, x: 0, y: 10)
        })
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
} ```

2 Answers 2

2

In SwiftUI, the View reflects the State data, so you don't modify the View directly, but rather modify the State data, and build the View based on the State. This is a core principle behind SwiftUI, and it allows you to separate the View concerns from the data that drives it (ViewModel in some lingo).

So, let's assume that we have a data model for a Card (make it conform to Identifiable - this will be needed later):

struct Card: Identifiable {
  let id = UUID()
  let name: String
}

And let's define an array of cards as a state variable in your View:

@State private var cards: [Card] = [Card(name: "foo")]

Then the body could display these cards with a ForEach or in a List view:

var body = some View {
  VStack() {
    Button("Add Card") {
       self.cards.append(Card(name: "I'm an added card"))
    }
    ForEach(cards) { card in
       CardView(for: card) // if your CardView had parameters
    }
  }
}

What happens is that the closure for the button adds a new Card instance to the cards state variable. That's it. It doesn't change anything in the View directly. The View sees the change (that's what SwiftUI does behind the scenes) and re-renders itself.

The reason you needed a Card to conform to Identifiable was to let the ForEach know how to uniquely identify each card. Without conforming to identifiable, you could use a key path like so:

ForEach(cards) { card in
  // ...
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much! you have provided a very clear and coherent explanation. Amazing stuff. Problem solved.
0

check this out:

import SwiftUI

struct ContentView: View {

    @State var cards: [CardView] = [CardView()]



    var body: some View {
        VStack {
            TextButton(action: {
                print("Button tapped")
                self.cards.append(CardView())

            }, text: "new card")
            ZStack {
                ForEach(cards, id: \.self) { card in
                    card
                        .rotationEffect(card.angle)

                }

            }
        }
    }
}

struct CardView: View, Hashable, Identifiable {

    var id = UUID()

    var angle : Angle {
        let angle = Angle(degrees: Double.random(in: 0...30))
        print(angle.degrees)
        return angle
    }
    var body: some View {
        ZStack {
            Rectangle()
                .fill(Color(#colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)))
                .frame(width: 100, height: 100 * 1.618)
                .cornerRadius(16)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.1), radius: 1, x: 0, y: 1)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.2), radius: 10, x: 0, y: 10)

            VStack {
                Text("Card \(angle.degrees)")
                    .font(.system(size: 10) )
                    .foregroundColor(.white)
                    .bold()
            }
        }
    }
}


struct TextButton: View {
    let action: () -> Void
    let text: String

    var body: some View {
        Button(action: action, label: {
            Text(text)
                .padding(.horizontal, 16)
                .padding(.vertical, 16)
                .foregroundColor(.white)
                .background(Color.blue)
                .cornerRadius(.infinity)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.1), radius: 1, x: 0, y: 1)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.2), radius: 10, x: 0, y: 10)
        })
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.