对于swift中的循环似乎随机选择增量

时间:2016-05-09 14:06:44

标签: ios swift sprite-kit

我有一个执行动画的for循环,然后在完成时删除它们,我试图在完成时调用另一个方法。这是我的代码:

func animateMatch(completion: () -> ()) {
    var movingShape = level.shapeAtColumn(pointsContainingShapeArray[0].Column, row: pointsContainingShapeArray[0].Row)
    let destinationShape = level.shapeAtColumn(pointsContainingShapeArray[0].Column, row: pointsContainingShapeArray[0].Row)

    for everyShape in 1..<pointsContainingShapeArray.count {
        movingShape = level.shapeAtColumn(pointsContainingShapeArray[everyShape].Column, row: pointsContainingShapeArray[everyShape].Row)

        let Duration: NSTimeInterval = 1

        let moveShapes = SKAction.moveTo((destinationShape?.sprite!.position)!,duration: Duration)
        moveShapes.timingMode = .EaseOut

        movingShape?.sprite?.runAction(moveShapes, completion: {
            movingShape?.sprite?.removeFromParent()
            print("Removed shape \(everyShape)")
            if everyShape == pointsContainingShapeArray.count {
                completion()
            }
        })

    }
}

基本上这个想法是在第一个位置之后的数组中的每个形状移动到第一个位置的位置,然后将其从场景中移除。这样可以正常工作,但我的完成每次都会随机调用。所以最后我在那里添加了print语句。这是输出:

Removed shape 3
Removed shape 1
Removed shape 4
Removed shape 2

此时我非常沮丧,我觉得是时候堆栈溢出了。我无法弄清楚这里发生了什么。谢谢你的帮助!

以下是调用此方法的代码:

func handleSwipe(move: Move) {
    view.userInteractionEnabled = false

    level.performMove(move)

    scene.animateMove(move) {
        self.view.userInteractionEnabled = true
        if hasMatch {
            self.view.userInteractionEnabled = false

            self.scene.animateMatch() {
                self.scene.addNewSpritesForShapes(pointsContainingShapeArray)
                hasMatch = false
                self.view!.userInteractionEnabled = true

            }

        }

    }

}

1 个答案:

答案 0 :(得分:2)

问题不在于for循环,而是运行操作的异步性质。

当您调用moveShapes操作时,它会在原始线程上调用完成之前异步运行。这可以按任何顺序发生。您可以通过同步调用打印来自己查看:

for everyShape in 1..<pointsContainingShapeArray.count {
    print("Synchronous loop: \(everyShape)")
}

我认为您最后使用dispatch_group_t会更好:

func animateMatch(completion: () -> ()) {
    var movingShape = level.shapeAtColumn(pointsContainingShapeArray[0].Column, row: pointsContainingShapeArray[0].Row)
    let destinationShape = level.shapeAtColumn(pointsContainingShapeArray[0].Column, row: pointsContainingShapeArray[0].Row)
    // HERE
    let group = dispatch_group_create()
    dispatch_group_notify(group, dispatch_get_main_queue(), completion) 
    //
    for everyShape in 1..<pointsContainingShapeArray.count {
        // HERE
        dispatch_group_enter(group)
        //
        movingShape = level.shapeAtColumn(pointsContainingShapeArray[everyShape].Column, row: pointsContainingShapeArray[everyShape].Row)

        let Duration: NSTimeInterval = 1

        let moveShapes = SKAction.moveTo((destinationShape?.sprite!.position)!,duration: Duration)
        moveShapes.timingMode = .EaseOut

        movingShape?.sprite?.runAction(moveShapes, completion: {
            movingShape?.sprite?.removeFromParent()
            print("Removed shape \(everyShape)")
            // HERE
            dispatch_group_leave(group)
            //
        })

    }
}