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

How do I refresh my view?

Forums > SwiftUI

When I add cards(images) to a players hand, I want to then update the view to show the new cards, same if I delete cards from the hand. Thanks for the assist!

import SwiftUI

struct refresh: View {
    @State var showcards: [String] = ["Jack", "Harper", "Scout", "Elijah", "Jack", "Harper", "Scout", "Elijah", "oker_red", "oker_black"]
    @State var names: [String] = ["Kim","Debbi","Elijah","Scout"]
    @State var p1hand: [String] = ["2_of_spades", "3_of_spades", "4_of_spades", "5_of_spades", "6_of_spades", "7_of_spades", "8_of_spades", "9_of_spades", "10_of_spades", "jack_of_spades", "queen_of_spades", "king_of_spades", "ace_of_spades"]
    @State private var position = CGPoint(x: 20, y: 25)

    var body: some View {
        ZStack {
            Color.teal.ignoresSafeArea()
            VStack {
                HStack {
                    ForEach(0..<showcards.count, id: \.self) { index in
                        cardView3(position: position, showcard: p1hand[index])
                    }
                }
            }
            VStack {
                Button(action: {
                    print("card added to hand")
                    p1hand.append("ace_of_diamonds")
                    print("p1 cards: \(p1hand)")
                    refresh()
                }, label: {
                    Text("add on to hand").font(.title3).bold().frame(width: 175, height: 40).background(Color.green).foregroundColor(.white).cornerRadius(10)})
            }
        }
    }
}

struct cardView3: View {
    @State private var card1pos: CGPoint = CGPoint(x: 30, y: 40)
    @State var position: CGPoint
    @State var showcard: String
    @GestureState private var pressing: Bool = false
    @State private var expand: Bool = false
    var body: some View {
        Image(showcard).resizable().frame(width: 40, height: 60).position(x: position.x, y: position.y)
            .opacity(pressing ? 0 : 1.0)
            .gesture(LongPressGesture(minimumDuration: 1).updating($pressing){value,state,transaction in state = value
                transaction.animation = Animation.easeInOut(duration: 0.5)
            }.onEnded { value in expand = true})
            .gesture(DragGesture().onChanged { position = $0.location})
    }
}

2      

@formank may have skipped important lessons on the way View structs redraw themselves:

When I add cards to a player's hand, the view [should] show the new cards, same if a player deletes cards from the hand

It appears you have skipped some valuable lessons.

In short, it seems you are trying to mix procedural language skills with SwiftUI's declarative approach. In a procedural language, you would determine when some data was updated, then TELL the code what to draw in the next several lines.

In a declarative approach, you setup a data source, and wire your view to simply display what's in the data source. Any time the data source changes, your view will draw according to the new values in your data.

Declare what you want to See

In SwiftUI, your views should just reflect the state of your model. In your case you have a player's hand of cards. If that hand has four cards in it, your view should show four cards. If you add a card, the view will detect the change in your model and redraw itself automatically to display five cards.

Just update your model, and the view will redraw itself.

Sample Code

Here is some sample code for you to paste into a new project. Notice how the CardView shows just ONE card. Notice how the HandView shows the cards that are in the player's hand.

Also notice the buttons add a NEW card, or REMOVE an existing card. The HandView detects when the myHand variable changes. When it changes, the HandView redraws itself.

Sample Code

// This is the view to show the cards in the player's hand.
struct HandView: View {
    // myHand is the model.
    // When you CHANGE the model, any view that references
    // this model will UPDATE.
    @State private var myHand = [CardView(), CardView()] // Collection of Cards
    var body: some View {
        VStack {
            HStack {
                // HERE! Here you are changing the model.
                Button { myHand.append(CardView()) } label: {
                    Image(systemName: "plus.square.fill") }
                // ALSO HERE. Here you change the model
                Button { myHand.removeLast() } label: {
                    Image(systemName: "minus.circle.fill")
                }
            }.font(.largeTitle)
            ScrollView {
                // Here you display the MODEL
                // If myHand changes, this view code
                // will REDRAW itself.
                ForEach(myHand) { cardInMyHand in
                    cardInMyHand // <-- Show the card
                }
            }.animation(.default, value: myHand)
        }.padding()
    }
}

// This is the view to show ONE card.
struct CardView: View, Identifiable, Hashable {
    var id = UUID().uuidString
    // Pick random elements for variety.
    let cardColor: [Color]  = [.red, .teal, .indigo, .blue, .green]
    var cardTitle: [String] = ["Ace", "Two", "Three", "Seven", "Jack", "Queen"]
    var cardSuit:  [String] = ["suit.club.fill", "suit.heart.fill", "suit.spade.fill", "suit.diamond.fill"]
    var body: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 15)
                .fill(cardColor.randomElement()!.opacity(0.4))
            VStack{
                Image(systemName: cardSuit.randomElement()!)
                Text(cardTitle.randomElement()!)
            }.font(.title)
        }.frame(width: 100, height: 125)
    }
}

Keep Coding

Are you following the 100 Days of SwiftUI? You code suggests you missed some key concepts. I would recommend you revisit several of the earlier lessons.

2      

thanks! I come from a FORTRAN background from many years ago!

2      

thanks! I come from a FORTRAN background from many years ago!

2      

Hacking with Swift is sponsored by RevenueCat.

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

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

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

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.