UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Project 17, part 4 - Ending the app with allowsHitTesting() - Issue the cards didn't appeared enough

Forums > 100 Days of SwiftUI

Hi everyone,

I am on day 89 (Project 17, part 4 - Ending the app with allowsHitTesting()). When testing on simulator, after removing all cards:

  • If I immediately pressed the button "Start Again", then only few cards appeared (may be 0, 1, 2, or 3 cards ...).
  • But if I waited for some more seconds, then pressed the button "Start Again", it could show enough cards (10 ones as example).

Here is the code of ContentView.swift:

//
//  ContentView.swift
//  Flashzilla
//
//  Created by TIEN on 23/02/2024.
//

import SwiftUI

extension View{
    func stacked(at position: Int, in total: Int) -> some View{
        let offset = Double(total - position)
        return self.offset( y: offset * 10)
    }
}

struct ContentView: View {
    @Environment(\.accessibilityDifferentiateWithoutColor) var accessibilityDifferentiateWithoutColor
    @Environment(\.scenePhase) var scenePhase
    @State private var cards = Array<Card>(repeating: .example, count: 10)
    @State private var timeRemaining = 100
    @State private var isActive = true

    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        ZStack{
            Image(.background)
                .resizable()
                .ignoresSafeArea()
            VStack{
                Text("Time: \(timeRemaining)")
                    .font(.largeTitle)
                    .foregroundStyle(.white)
                    .padding(.horizontal, 20)
                    .padding(.vertical, 5)
                    .background(.black.opacity(0.75))
                    .clipShape(.capsule)
                ZStack{

                        ForEach(0..<cards.count, id:\.self){ index in
                            CardView(card: cards[index]){
                                withAnimation{
                                    removeCard(at: index)
                                }

                            }
                            .stacked(at: index, in: cards.count)
                            .allowsHitTesting(index == cards.count - 1)
                        }
                }
                .allowsHitTesting(timeRemaining > 0)
                //For testing
                Text("Card remaining: \(cards.count)")
                if cards.isEmpty {
                    Button("Start Again", action: resetCards)
                        .padding()
                        .background(.white)
                        .foregroundStyle(.black)
                        .clipShape(.capsule)
                        .padding()
                }
            }
            if accessibilityDifferentiateWithoutColor {
                VStack{
                    Spacer()
                    HStack{
                        Image(systemName: "xmark.circle")
                            .padding()
                            .background(.black.opacity(0.7))
                            .clipShape(.circle)
                        Spacer()
                        Image(systemName: "checkmark.circle")
                            .padding()
                            .background(.black.opacity(0.7))
                            .clipShape(.circle)
                    }
                    .foregroundStyle(.white)
                    .font(.largeTitle)
                    .padding()
                }
            }

        }
        .onReceive(timer){time in
            guard isActive else {return}
            if timeRemaining > 0 {
                timeRemaining -= 1
            }
        }
        .onChange(of: scenePhase) { oldPhase, newPhase in
            if newPhase == .active {
                if cards.isEmpty == false{
                    isActive = true
                }
            }else {
                isActive = false
            }
        }
    }
    func removeCard(at index: Int){
        guard index >= 0 else {return}
        cards.remove(at: index)
        if cards.isEmpty {
            isActive = false
        }
    }
    func resetCards(){
        cards.removeAll()
        cards = Array<Card>(repeating: .example2, count: 10)
        timeRemaining = 100
        isActive = true
    }
}

#Preview {
    ContentView()
}

Please help me to solve the problem.

Thank you!

   

I don't think my solution is related to your issue but I noticed in your resetCards() method, you're reinitialising cards the array with .example2 instead of .example when you first loaded ContentView.

  func resetCards(){
        cards.removeAll()
        cards = Array<Card>(repeating: .example2, count: 10)
        timeRemaining = 100
        isActive = true
    }

Could you try changing it to .example instead?

   

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

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.