I understand quite well the SKAction API but I cannot achieve to have good code when running sequential code on multiple nodes.

Here is a sample code (simplified) :

```
import SpriteKit

class GameScene: SKScene {

    weak var node1: SKNode!
    weak var node2: SKNode!

    override func didMove(to view: SKView) {
        super.didMove(to: view)
        cacheUI()
        runSampleSequence()
    }

    private func cacheUI() {
        // Fetch nodes from associated SKS file
        node1 = self.childNode(withName: "node1")!
        node2 = self.childNode(withName: "node2")!
    }

    private func runSampleSequence() {
        // I want node1 to fadeIn
        // then node2 to fadeIn
        // then node1 to fadeOut
        // then node2 to fadeOut
        node1.run(SKAction.sequence([
            SKAction.fadeIn(withDuration: 1),
            SKaction.run { [weak self] in
                self.node2.run(SKAction.fadeIn(withDuration: 2))
            },
            SKAction.fadeOut(withDuration: 4),
            SKaction.run { [weak self] in
                self.node2.run(SKAction.fadeOut(withDuration: 3))
            }
        ]))
    }
}

```

The previous code will run perfectly, but will result with boilerplate code if we add node3, node4 ... I would like to be able to refactor it to be easier to read and maintain given specifications. Something like :

```
// Does not compile
self.run(SKAction.sequence([
    node1.fadeIn(withDuration: 1),
    node2.fadeIn(withDuration: 2),
    node1.fadeOut(withDuration: 4),
    node2.fadeOut(withDuration: 3)
]))

```

Can I achieve this ? I want the business code to appear as clear as possible.

How does SKAction.sequence(\_:) behave exactly when using SKAction.run { \_ }, does the next action is guarantee to be ran after the last SKAction.run block's instruction executes (and what if it itself perform asynchronous calls) ?

Bonus question: Am I right to set self as weak in closure capture lists ? As I do not want it to be kept as a strong reference when dismissing the game scene.

**EDITED:**
Well, something like that could do the job but the second fade starts before the first one ends ...

```
private func runSampleSequence() {
    // I want node1 to fadeIn
    // then node2 to fadeIn
    // then node1 to fadeOut
    // then node2 to fadeOut
    self.run(SKAction.sequence([
        node1.fadeIn(withDuration: 1),
        node2.fadeIn(withDuration: 2),
        node1.fadeOut(withDuration: 4),
        node2.fadeOut(withDuration: 3)
    ]))
}

```

by returning actions from an SKNode extension :

```
extension SKNode {
    func fadeIn(withDuration: TimeInterval) -> SKAction {
        let action = SKAction.run {
            self.run(SKAction.fadeIn(withDuration: withDuration))
        }
        return action
    }
    //TODO: Extend for each base SKAction ...
}

```