嵌套" for"中的并发SKA序列的完成块循环?

时间:2018-06-12 22:15:03

标签: swift sprite-kit grand-central-dispatch

我试图在" for"中运行一组SKActions。循环,如下面的代码所示。序列应该像这样运行:

对于第一个超级节点......

  1. 同时对所有子子节点运行openingAction;什么时候完成......
  2. 同时对所有子spriteNodes运行variableDurationActions;什么时候完成......
  3. 同时对所有子子节点运行closingAction,并且同时运行...
  4. 对于第二个超级节点......

    1. 同时对所有子子节点运行openingAction;什么时候完成......
    2. 每个超节点都会重复这个三步过程。

      第一个问题是,尽管我可以编写一个闭包来等待一个动作在开始另一个动作之前完成,但我不知道如何在#34; for"中进行多个并发动作。 34;循环。在第1步和第2步以及第2步和第3步之间会出现此问题。在2到3之间,更糟糕的是,因为步骤2中的操作持续时间可能会有很大差异。

      第二个问题是我不知道如何编写一个完成处理程序或一些等价物来使openingAction和下一次openAction迭代同时运行,但是在下一次迭代中的variableDurationActions之前。

      使用SpriteKit的工具,我是否正在努力做到这一点?或者我应该使用调度组吗?我正在寻找优雅的解决方案,因为我的代码很复杂。

      for superNode in scene.children {
      
          for subNode in superNode.children {
      
              // All openingActions should run first
              subNode.run(openingAction)
      
                  for spriteNode in subNode.children {
      
                      // These variableDurationActions should run concurrently, second
                      spriteNode.run(variableDurationAction)
                  }
      
              // All closingActions should run third AND
              // concurrently with the openingActions in the next iteration
              subNode.run(closingAction)
          }
      }
      

1 个答案:

答案 0 :(得分:0)

我最终想出了一个解决方案,通过分离时间上不同的处理步骤,创建一个带有两个检查点的调度组,并使主要功能(在底部,下面)通过调用自身来遍历超节点。

对我来说这似乎有点笨拙,但这就是它的样子:

let dispatchGroup = DispatchGroup()

// Step 1
func runOpeningActions() {
    for subNode in superNode.children {
        dispatchGroup.enter()
        // All openingActions should run concurrently, first
        subNode.run(openingAction) { 
            dispatchGroup.leave() 
        }
    }
}

// Step 2
func runVariableDurationActions {
    for subNode in superNode.children {
        dispatchGroup.enter()
        for spriteNode in subNode.children {
            // These variableDurationActions should run concurrently, second
            spriteNode.run(variableDurationAction) {
                dispatchGroup.leave()
            }
        }
    }
}

// Step 3 – to run concurrently with the next Step 1
func runClosingActions() {
    for subNode in superNode.children {
        dispatchGroup.enter()
        // All closingActions should run concurrently, third AND
        // concurrently with the openingActions in the next iteration
        subNode.run(closingAction) { 
            dispatchGroup.leave() 
        }
    }
}

var nodeIndex = 0

// Main function – iterates over Steps 1, 2, and 3
func runAllActions() {
    let superNode = scene.children[nodeIndex]
    runOpeningActions()
    dispatchGroup.notify(queue: .main) {
        runVariableDurationActions()
        dispatchGroup.notify(queue: .main) {
            runClosingActions()
            nodeIndex += 1
            if nodeIndex < scene.children.count {
                runAnimation()
            } else {
                // No more superNodes to process; leave the function
            }
        }
    }
}

// Main function call
runAllActions()