NEW: My new book Pro SwiftUI is out now – level up your SwiftUI skills today! >>

SOLVED: Day 91: Flashzilla challenge #2

Forums > 100 Days of SwiftUI

I'm having real trouble with the second challenge in the Flashzilla project. I'm trying to work out how to tell from the removeCard function whether a card was answered correctly or incorrectly, and I started out trying to modify the closure so that I could call self.removal?(correctAnswer) after the DragGesture in CardView.swift. However, I've tried a number of ways to get this to work and I'm really struggling to do so – can anyone give me any hints as to how they've done this?

1      

I have a same problem here and I've been stuck on this for a while now :( : https://www.hackingwithswift.com/forums/100-days-of-swiftui/day-91-flashzilla-challenge-2-3/7793

Hope you'll get some response cause I'd like to move forward and it's really frustrating :(

1      

I did eventually work this out! I went back to the Unwrap app and revised my closures, and came up with the below.

In ContentView.swift I inserted this code in place of the previous code:

let removal = { (correct: Bool) in
    print(correct)
    if self.removeWrongAnswers || correct {
        withAnimation {
            self.removeCard(at: index)
        }
    } else {
        // the DispatchQueue bit fixes the bug (source: HwS forums)
        let wrongCard = self.cards.remove(at: index)
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            self.cards.insert(wrongCard, at: 0)
        }
    }
}

CardView(card: self.cards[index], removal: removal)
    .stacked(at: index, in: self.cards.count)
    .allowsHitTesting(index == self.cards.count - 1)
    .accessibility(hidden: index < self.cards.count - 1)

and then in CardView.swift I inserted this code in place of the existing .onEnded modifier:

.onEnded { _ in
    if abs(self.offset.width) > 100 {
        var correct: Bool

        if self.offset.width > 0 {
            self.feedback.notificationOccurred(.success)
            correct = true
        } else {
            self.feedback.notificationOccurred(.error)
            correct = false
        }

        self.removal?(correct)
    } else {
        self.offset = .zero
    }
}

3      

@johncoxon Thansk!! It's working for me now too :)

2      

OMG, I've just spent so long trying to figure this out.

I've then tried to implement your code but couldn't get that to work either. Then I noticed the comment about about the bug and the dispatch queue code.

Turns out my first attempt yesterday was working except for the bug... I've just added the dispatch queue code around my card insertion and boom, all working fine.

So frustrating, but also kind of a relief that I was so close to resolving this except for the bug. Incidentally, do you have a link to a discussion around the bug?

edit:

Don't worry, I've found it: https://www.hackingwithswift.com/forums/100-days-of-swiftui/day-91-flashzilla-challenges-can-t-seem-to-readd-a-card-successfully/2037/6401

1      

Hello everyone! I'm also stucked on this challenge too. But I found better solution with less code and without DispatchQueue.main.

So Paul said that we should rethink our Card model and add an UUID(). When you create your List() it's identify your objects by UUID of the Card. And it's cause our problems. SwifUI manage object with the same UUID trying to remove from Array and append to it back almost at the same time .

So when you are trying to move Card to the end just set a new UUID() to the card. And everything will works fine without using delay on DispathchQueue.

   

I'm also and still having trouble, even after integrating Paul's solution. He hasn't shown this specific case in the video, so I don't know whether it would work for him or not.

First of all, I'm not uising remove and insert, but

if reinsert {
    cards.move(fromOffsets: IndexSet(integer: index), toOffset: 0)
} else {
    cards.remove(at: index)
}

and my list is using Array(cards.enumerated()) with item.element and item.offset. (Card has UUID and is Identifiable and Hashable).

However it still causes problems in certain circumstances. If I swipe everything to left only, it seems to work.

As soon as I swipe one element to the right and I reach the former end of the list, the next item is not clickable. Easy to reproduce: Just swipe everything to right, then the last element to left. It reappears, but is not draggable.

Weird combinations also exist with some left, some right and from some elment on, it's not draggable anymore.

Anyone else facing this issue?

   

Nevermind… comparison line by line revealed one wrong value to the reinsert parameter (both got a true, but when swiping to the right, the offset asn't reset to .zero. That caused the unexpected behavior.

   

Hacking with Swift is sponsored by MadMachine

SPONSORED Want to explore your Swift skill outside of the Apple world? Join the MadMachine community and start to program microcontrollers in Swift.

Get it 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.