问题
I am trying to get three functions to call, one after the other after each has completed a specific number of loops.
I have succeeded in trying to call a second function once a first function with a count has completed.
I am struggling to do a third, fourth, etc. The problem I appear to have is in the syntax for the call in the view did load:
midGroundlevelMovingSlow(midGroundlevelMovingMedium(midGroundlevelMovingFast()))
Does not work for the three functions where as:
midGroundlevelMovingSlow(midGroundlevelMovingMedium)
Did work for two.
I have tried altering the brackets, adding self. etc with no success.
The code that I have used for the three functions (slow, medium and fast) is:
func midGroundlevelMovingSlow(completion: (()->Void)?) {
let moveLevelImage = SKAction.moveByX(-self.frame.size.width, y: 0, duration: gameSpeed)
let replaceLevelImage = SKAction.moveByX(self.frame.size.width, y: 0, duration: 0)
let movingAndReplacingLevelImage = SKAction.repeatAction(SKAction.sequence([moveLevelImage,replaceLevelImage]), count: 2)
var callCount = 2
mgImage.runAction(movingAndReplacingLevelImage){ () -> Void in
if --callCount == 0 {
self.foreGroundLevelMovingMedium(self.foreGroundLevelMovingFast)
}
}
mgImage2.runAction(movingAndReplacingLevelImage){ () -> Void in
if --callCount == 0 {
self.foreGroundLevelMovingMedium(self.foreGroundLevelMovingFast)
}
}
}
Followed by:
func midGroundlevelMovingMedium(completion: (()->Void)?) {
let moveLevelImage = SKAction.moveByX(-self.frame.size.width, y: 0, duration: gameSpeed / 2)
let replaceLevelImage = SKAction.moveByX(self.frame.size.width, y: 0, duration: 0)
let movingAndReplacingLevelImage = SKAction.repeatAction(SKAction.sequence([moveLevelImage,replaceLevelImage]), count: 4)
var callCount = 2
mgImage.runAction(movingAndReplacingLevelImage){ () -> Void in
if --callCount == 0 {
self.midGroundlevelMovingFast()
}
}
mgImage2.runAction(movingAndReplacingLevelImage){ () -> Void in
if --callCount == 0 {
self.midGroundlevelMovingFast()
}
}
}
and finally:
func midGroundlevelMovingFast() {
let moveLevelImage = SKAction.moveByX(-self.frame.size.width, y: 0, duration: gameSpeed / 4)
let replaceLevelImage = SKAction.moveByX(self.frame.size.width, y: 0, duration: 0)
let movingAndReplacingLevelImage = SKAction.repeatAction(SKAction.sequence([moveLevelImage,replaceLevelImage]), count: 8)
mgImage.runAction(movingAndReplacingLevelImage)
mgImage2.runAction(movingAndReplacingLevelImage)
}
When I use the last two in the same format as I used before it works so I think the code is good. Somewhere in the line i'm using to call the function in the viewdidload is either wrong or cannot be done like this.
Can anyone explain to me why this is not working please?
Thanks,
Steven
Update:
Ok, thanks again for your help and I feel that I'm so close now. However I'm still getting a final error that I don't know how to resolve.
I now have:
//Functions for the flow of the level, controlling the speed of the background images and the number of loops each will go through before increasing in speed.
func midGroundLevelMovingSlow(completion: (()->Void)?) {
let moveLevelImage = SKAction.moveByX(-self.frame.size.width, y: 0, duration: gameSpeed)
let replaceLevelImage = SKAction.moveByX(self.frame.size.width, y: 0, duration: 0)
let movingAndReplacingLevelImage = SKAction.repeatAction(SKAction.sequence([moveLevelImage,replaceLevelImage]), count: 4)
var callCount = 2
mgImage.runAction(movingAndReplacingLevelImage){ () -> Void in
if --callCount == 0 {
completion?()
}
}
mgImage2.runAction(movingAndReplacingLevelImage){ () -> Void in
if --callCount == 0 {
completion?()
}
}
}
Followed by:
func midGroundLevelMovingMedium(completion: (()->Void)?) {
let moveLevelImage = SKAction.moveByX(-self.frame.size.width, y: 0, duration: gameSpeed / 2)
let replaceLevelImage = SKAction.moveByX(self.frame.size.width, y: 0, duration: 0)
let movingAndReplacingLevelImage = SKAction.repeatAction(SKAction.sequence([moveLevelImage,replaceLevelImage]), count: 4)
var callCount = 2
mgImage.runAction(movingAndReplacingLevelImage){ () -> Void in
if --callCount == 0 {
completion?()
}
}
mgImage2.runAction(movingAndReplacingLevelImage){ () -> Void in
if --callCount == 0 {
completion?()
}
}
}
and then:
func midGroundLevelMovingFast(completion: (()->Void)?) {
let moveLevelImage = SKAction.moveByX(-self.frame.size.width, y: 0, duration: gameSpeed / 4)
let replaceLevelImage = SKAction.moveByX(self.frame.size.width, y: 0, duration: 0)
let movingAndReplacingLevelImage = SKAction.repeatAction(SKAction.sequence([moveLevelImage,replaceLevelImage]), count: 4)
var callCount = 2
mgImage.runAction(movingAndReplacingLevelImage){ () -> Void in
if --callCount == 0 {
completion?()
}
}
mgImage2.runAction(movingAndReplacingLevelImage){ () -> Void in
if --callCount == 0 {
completion?()
}
}
}
Which is called with:
midGroundLevelMovingSlow(completion: {
midGroundLevelMovingMedium(completion: {
midGroundLevelMovingFast(completion: {
print "Finished"
})
})
})
Which gives me an error on each line "extraneous argument label "completion" in call"
Does anyone know why this is the case?
Thanks,
Steven
Update:
It was just a case of deleting the extraneous "completion" word.
Works now, brilliant.
回答1:
In the completion handler in runAction you should be calling the completion handler in your method
mgImage.runAction(movingAndReplacingLevelImage){ () -> Void in
if --callCount == 0 {
completion()
}
}
However calling the methods like this growing increasingly ugly so I think it's a good idea to look into how to solve this with SKAction.sequence and SKAction.group.
https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKAction_Ref/#//apple_ref/occ/clm/SKAction/sequence:
https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKAction_Ref/#//apple_ref/occ/clm/SKAction/group:
I haven't worked much with SpriteKit so I can't reply tell you by hearth how to do it but I'm sure there is a solution for what you are trying to do built in to SpriteKit.
i.e.
func midGroundlevelMovingSlow(completion: (()->Void)?) {
let moveLevelImage = SKAction.moveByX(-self.frame.size.width, y: 0, duration: gameSpeed)
let replaceLevelImage = SKAction.moveByX(self.frame.size.width, y: 0, duration: 0)
let movingAndReplacingLevelImage = SKAction.repeatAction(SKAction.sequence([moveLevelImage,replaceLevelImage]), count: 2)
var callCount = 2
mgImage.runAction(movingAndReplacingLevelImage){ () -> Void in
if --callCount == 0 {
completion()
}
}
mgImage2.runAction(movingAndReplacingLevelImage){ () -> Void in
if --callCount == 0 {
completion()
}
}
}
in call
midGroundlevelMovingSlow(completion: {
self.foreGroundLevelMovingMedium(completion: {
self.foreGroundLevelMovingFast(completion:{})
})
})
来源:https://stackoverflow.com/questions/33319558/how-do-i-do-consecutive-function-calls-using-the-completion-handler-in-swift-on