How do I do consecutive function calls using the completion handler in Swift on an SKSpriteNode?

眉间皱痕 提交于 2020-01-05 15:42:07

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!