【问题标题】:How do I do consecutive function calls using the completion handler in Swift on an SKSpriteNode?如何在 SKSpriteNode 上使用 Swift 中的完成处理程序进行连续函数调用?
【发布时间】:2016-01-24 00:09:14
【问题描述】:

我正在尝试调用三个函数,在每个函数完成特定数量的循环后一个接一个地调用。

一旦具有计数的第一个函数完成后,我已成功尝试调用第二个函数。

我正在努力做第三个、第四个等。我似乎遇到的问题在于视图中调用的语法确实加载了:

midGroundlevelMovingSlow(midGroundlevelMovingMedium(midGroundlevelMovingFast()))

不适用于以下三个功能:

midGroundlevelMovingSlow(midGroundlevelMovingMedium)

确实为两个人工作。

我尝试更改括号,添加 self.等等都没有成功。

我用于三个功能(慢、中、快)的代码是:

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)
        }
    }
}

接着是:

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()
        }
    }
}

最后:

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)
}

当我以与之前使用的格式相同的格式使用最后两个时,我认为代码很好。在我用来调用 viewdidload 中的函数的行中的某处要么是错误的,要么不能像这样完成。

谁能向我解释一下为什么这不起作用?

谢谢,

史蒂文

更新:

好的,再次感谢您的帮助,我觉得我现在已经很接近了。但是,我仍然遇到一个我不知道如何解决的最终错误。

我现在有:

    //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?()
            }
        }
    }

接着是:

    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?()
            }
        }
    }

然后:

    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?()
            }
        }
    }

调用方式:

    midGroundLevelMovingSlow(completion: {
        midGroundLevelMovingMedium(completion: {
            midGroundLevelMovingFast(completion: {
                print "Finished"
            })
        })
    })

这在每一行“调用中的外部参数标签“完成””上给我一个错误

有人知道为什么会这样吗?

谢谢,

史蒂文

更新:

这只是删除无关的“完成”字的情况。

现在工作,太棒了。

【问题讨论】:

    标签: swift sprite-kit ios9


    【解决方案1】:

    在 runAction 的完成处理程序中,您应该在方法中调用完成处理程序

    mgImage.runAction(movingAndReplacingLevelImage){ () -> Void in
            if --callCount == 0 {
                completion()
            }
        }
    

    但是,这样的方法越来越难看,所以我认为研究如何使用 SKAction.sequence 和 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:

    我没有用 SpriteKit 做太多工作,所以我无法回复告诉你如何做,但我确信 SpriteKit 内置了你想要做的事情的解决方案。

    即

    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()
            }
        }
    }
    

    通话中

    midGroundlevelMovingSlow(completion: {
        self.foreGroundLevelMovingMedium(completion: {
            self.foreGroundLevelMovingFast(completion:{})
        })
    })
    

    【讨论】:

    • 再次感谢您的帮助。如前所述,我可以让它适用于我们讨论过的两个功能,而且效果很好。当我添加第三个函数时,即在第二个完成时调用,在第一个完成时调用,它会倒下。
    • 因为您的代码没有调用“completion()”,它调用的是实际方法,您应该在作为参数发送到该方法的块中调用该方法。将您的代码更改为我在答案中写的内容。
    • 谢谢。我用它再次推动事情向前发展,并用看起来像最终问题的代码更新了代码。史蒂文
    猜你喜欢
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    • 2018-10-23
    • 2021-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多