0
votes

I want to create and run some SKAction. After the SKAction, the program will print a message.

let actLoop = SKAction.run {
for i in 1 ... 10 {

    self.stone[i - 1].position = CGPoint(x: 0 , y: -100)
    self.stone[i - 1].anchorPoint = CGPoint(x: 0.5, y: 0.5)
    self.stone[i - 1].size = CGSize(width: 50, height: 50)
    self.addChild(self.stone[i - 1])   

    let actionMove = SKAction.move(to: CGPoint(x: 0, y: 0), duration: 0.3)
    let actionRolling = SKAction.animate(with: stone[i - 1].arrayTexture, timePerFrame: 0.05)
    let actionSequence = SKAction.sequence([actionMove,actionRolling])
    stone[i - 1].run(actionSequence)
}

self.run(actLoop) {

print("Completed")

}

The program will not print the "Completed" message at the end but the message will appear about the same time the SKActions are executing. I want the message to appear only after all the SKActions have completed. I also tried this:

    self.run(actLoop, completion: {
        //
        print("Completed")

        })

This also did not work. I cannot seem to get this right.

2

2 Answers

0
votes

I tried explaining this to you in another question. a for loop DOES NOT wait for actions to be finished before going on to the next item. The for loop processes all 10 of your items instantaneously (almost). Therefore the output you are experiencing is expected. There are a number of ways that you can do this, but some are more complex than others (ie. completion blocks). The easiest way to do this would just be to track the duration in the for loop and wait for that duration to fire the completion.

According to your code that you presented here ALL 10 items are presented to the screen at the same time, which is contradictory to the last question you asked on this topic.

for x in 0..<10 {
    self.run(.wait(forDuration: 1.0)) {
        print(x)
    }
}

will print out 0,1,2,3,4,5,6,7,8,9 on separate lines all at once 1 second after the code is run, because all the lines in the loop are processed all at once and told to wait 1 second before printing.

var delay: double = 1.0
for x in 0..<10 {
    self.run(.wait(forDuration: delay)) {
        print(x)
    }

    delay += 1
}

will print out 0,1,2,3,4,5,6,7,8,9 on separate lines 1 second after the prior one was printed with the last one taking 10 seconds total to output the code is run, because that lines in the loop are processed all at once and told to wait LONGER durations before printing.

var delay: double = 1.0
for x in 0..<10 {
    self.run(.wait(forDuration: delay)) {
        print(x)
    }

    delay += 1
}

self.run(.wait(forDuration: delay)) {
    print("all done adding objects")
}

this will output the final line ONLY AFTER the last one is done because we have waited the necessary time.

0
votes

Run blocks fire immediately and are completed when the block finishes, not when all actions inside the blocks finish.

Even if you you were to chain your actions one after another in the for loop, your run block will finish by the end of the update cycle.

I would recommend placing all of your actions into a sequence action if you plan on firing your code off one by one and then having a completion block.