Home > Software design >  How to use DispatchQueue to make a view appear and disappear after some time?
How to use DispatchQueue to make a view appear and disappear after some time?

Time:11-10

I want to make a view appear, do something, then disappear with DispatchQueue. I want to toggle the showHand to show the hand then toggleHandAnimation to make the hand move left and right. After some time e.g. 5 seconds, I want that hand to disappear.

I have an implementation below which seems to be working on the build but it seems like there would be a better way. I have the code below.

What is the guidance on implementing views where you want to run multiple tasks at different points in time async?

import SwiftUI

struct ContentView: View {
    @State var toggleHandAnimation: Bool = false
    @State var showHand: Bool = true
    
    var body: some View {
        if showHand {
            Image(systemName: "hand.draw")
                .font(Font.system(size: 100))
                .offset(x: toggleHandAnimation ? -40 : 0, y: 0)
                .animation(Animation.easeInOut(duration: 0.6).repeatCount(5))
                .onAppear {
                    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()   1, execute: {
                        toggleHandAnimation.toggle()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()   5, execute: {
                        showHand.toggle()
                        })
                    })
                }
        }
        
    }
}

enter image description here

CodePudding user response:

I think this is what you are looking for:

struct ContentView: View {
    @State var toggleHandAnimation: Bool = false
    @State var showHand: Bool = true
    
    var body: some View {
        ZStack {
            Color(uiColor: .systemBackground)
            if showHand {
                Image(systemName: "hand.draw")
                    .font(Font.system(size: 100))
                    .offset(x: toggleHandAnimation ? -40 : 0, y: 0)
                    .onAppear {
                        withAnimation(Animation.easeInOut(duration: 0.5).repeatCount(10)) {
                            toggleHandAnimation.toggle()
                        }
                        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()   5, execute: {
                            showHand.toggle()
                        })
                    }
            }
        }
    }
}

A few things, you should read up on intrinsic vs. extrinsic animations. You were trying to use an intrinsic one, but for a situation like this, it should be extrinsic(i.e., withAnimation(). Also, .animation(_ animation:) has been deprecated because it does not work well. You should be using .animation(_ animation:, value:).

Also, I aligned the time so that the animation ends and the hand disappears. The nice thing with using the withAnimation() is that you can animate multiple things occur with the same animation.

As you can see, you din't need to nest theDispatchQueues. You only needed the one to make the view disappear.

Lastly, I put this all in a ZStack and set a color on that, so that there was always a view to return. The reason is, this will crash if there is suddenly no view being returned. That is what would happen at the end of the animation with out the color. Obviously, you can have whatever view you want, that was just an example.

  • Related