title: Stop an action that runs forever, run another acton and resume the stopped action in SpriteKit
body: <p>I'm replicating the Chrome dinosaur game for a class project, and I ran into a problem where I have difficulties stopping the dinosaur from running when it jumps.</p>
  
  <p>I have three textures in a SKTextureAtlas: walk_1, walk_2 and jump, and I want the dinosaur to keep switching between walk_1 and walk_2 so it looks like it is walking. When I touch the screen, the dinosaur jumps, stops walking and the texture is set to jump until it falls on the ground again, and it starts walking again.</p>
  
  <p>However, when I touch the screen, the dinosaur does jump, but the texture is not changed and it keeps walking.</p>
  
  <p>I've tried all sort of solutions like combining removeAction and run, setting moveSpeed to 0 and 1 and simply running the jump sequence in touchesBegan without any additional settings, but none of the above works.</p>
  
  <p>My classmate tells me to use DispatchQueue.main.asyncAfter and surprisingly, it works! But I'm not quite sure why it works and want to know if there's any other solution that can achieve the same goal.</p>
  
  <pre><code>import SpriteKit
  
  class GameScene: SKScene {
  
      var dinoTexture:SKTextureAtlas!
      var dinosaur:SKSpriteNode!
      var walkForever:SKAction!
  
      required init?(coder aDecoder: NSCoder) {
          super.init(coder: aDecoder)
      }
  
      override init(size: CGSize) {
          super.init(size: size)
          dinoTexture = SKTextureAtlas(named: "dinosaur")
      }
  
      override func didMove(to view: SKView) {
  
          let walkOnce = SKAction.animate(with: [dinoTexture.textureNamed("walk_1.png"), dinoTexture.textureNamed("walk_2.png")], timePerFrame: 0.1)
          walkForever = SKAction.repeatForever(walkOnce)
  
          dinosaur = SKSpriteNode(texture: dinoTexture.textureNamed("walk_2.png"))
  
          dinosaur.run(walkForever, withKey: "dinosaurWalk")
  
          self.addChild(dinosaur)
      }
  
      override func touchesBegan(_ touches: Set&lt;UITouch&gt;, with event: UIEvent?) {
              dinosaur.removeAction(forKey: "dinosaurWalk")
              dinosaur.run(SKAction.sequence([SKAction.setTexture(dinoTexture.textureNamed("jump.png")), SKAction.moveBy(x: 0, y: 150, duration: 0.5), SKAction.moveBy(x: 0, y: -150, duration: 0.5), SKAction.setTexture(dinoTexture.textureNamed("walk_2.png"))]))
              DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                  self.dinosaur.run(self.walkForever, withKey: "dinosaurWalk")
          }
      }
  </code></pre>