打破动画块内的循环

时间:2017-03-20 12:16:05

标签: ios swift uiview uiviewanimation

我正在尝试在完成UIView动画后打破for循环。以下是以下片段:

public func greedyColoring() {
    let colors = [UIColor.blue, UIColor.green, UIColor.yellow, UIColor.red, UIColor.cyan, UIColor.orange, UIColor.magenta, UIColor.purple]

    for vertexIndex in 0 ..< self.graph.vertexCount {
        let neighbours = self.graph.neighborsForIndex(vertexIndex)
        let originVertex = vertices[vertexIndex]

        print("Checking now Following neighbours for vertex \(vertexIndex): \(neighbours)")

        var doesNotMatch = false

        while doesNotMatch == false {
            inner: for color in colors{
                UIView.animate(withDuration: 1, delay: 2, options: .curveEaseIn, animations: {
                    originVertex.layer.backgroundColor = color.cgColor
                }, completion: { (complet) in
                    if complet {
                        let matches = neighbours.filter {
                            let vertIdx = Int($0)!

                            print("Neighbour to check: \(vertIdx)")

                            let vertex = self.vertices[vertIdx-1]

                            if vertex.backgroundColor == color{
                                return true
                            }else{
                                return false
                            }
                        }

                        //print("there were \(matches.count) matches")

                        if matches.count == 0 {
                            // do some things
                            originVertex.backgroundColor = color
                            doesNotMatch = true
                            break inner
                        } else {
                            doesNotMatch = false
                        }
                    }
                })
            }
        }
    }
}

基本上这个方法迭代一个Graph并检查每个顶点及其邻居,并给顶点一个颜色,它的邻居都没有。这就是为什么它必须打破未使用的第一种颜色的迭代。我尝试使用Unlabeled循环但它仍然无法编译(break is only allowed inside a loop)。问题是我想要想象哪些颜色已经过测试。这就是为什么我使用UIView.animate()

有没有解决我的问题?

4 个答案:

答案 0 :(得分:4)

您需要了解,传递给animate函数的完成块在动画完成后被称为,这在for循环迭代后很长一段时间(在计算机时间内)通过颜色数组。您将持续时间设置为1秒,这意味着完成将在1秒后调用。由于for循环不等待你的动画完成,所以它们都将同时开始动画(也许会偏离几毫秒)。 for循环在动画完成之前已完成,这就是为什么打破for循环没有意义,因为它不再运行了!

如果您希望在调用print("Fire")函数之前添加UIView.animate调用,并在完成块中添加print("Finished")。在控制台中,您应该在所有完成之前看到所有 fire

您应该对动画进行排队,以便它们一个接一个地开始和结束。

答案 1 :(得分:2)

正如弗雷德里克所说,动画中你的for循环中下一个执行顺序与你的完成顺序不同步。这意味着无论您的块实现如何,for循环都将保持循环。 一个简单的解决方法是使用CABasicAnimation和CAAnimationGroup创建动画。因此,for循环的产品将是一组动画组中的动画链。

本教程将为您提供有关如何使用CABasicAnimation和CAAnimationGroup的建议:https://www.raywenderlich.com/102590/how-to-create-a-complex-loading-animation-in-swift

您可以使用此方法,因为断开for循环的条件由不依赖于动画本身的参数给出。一旦动画附加到您试图制作动画的视图,动画就会被执行。

希望这有帮助。

答案 2 :(得分:1)

Just modifying your code a little bit. Its a old school recursion but should work. Assuming all the instance variables are available here is a new version.   


public func greedyColoring(vertex:Int,colorIndex:Int){
       if  vertexIndex > self.graph.vertexCount { return }

       if colorIndex > color.count {return}

       let neighbours = self.graph.neighborsForIndex(vertexIndex)

       let originVertex = vertices[vertexIndex]

       let color = self.colors[colorIndex]

     UIView.animate(withDuration: 1, delay: 2, options: .curveEaseIn,   animations: {
            originVertex.layer.backgroundColor = color.cgColor
        }, completion: { (complet) in
            if complet {
                let matches = neighbours.filter {
                    let vertIdx = Int($0)!

                    print("Neighbour to check: \(vertIdx)")

                    let vertex = self.vertices[vertIdx-1]

                    //No idea what you are trying to do here. So leaving as it is.
                    if vertex.backgroundColor == color{
                        return true
                    }else{
                        return false
                    }
                }

                //print("there were \(matches.count) matches")

                if matches.count == 0 {
                    // do some things
                    originVertex.backgroundColor = color
                    greedyColoring(vertex: vertex++,colorIndex:0)
                } else {
                    greedyColoring(vertex: vertex,colorIndex: colorIndex++)
                }
            }
        })
    }


Now we can call this function simply

    greedyColor(vertex:0,colorIndex:0)

答案 3 :(得分:-1)

如前所述,完成块都是异步调用的,因此在for循环中不存在。最好的办法是在完成块中调用一个常用方法,它会在第一次调用后忽略所有内容。

var firstMatch: UIColor?

func foundMatch (_ colour: UIColor)
{
    if firstMatch == nil
    {
        firstMatch = colour
        print (firstMatch?.description ?? "Something went Wrong")
    }
}


let colours: [UIColor] = [.red, .green, .blue]

for colour in colours
{
    UIView.animate(withDuration: 1.0, animations: {}, completion:
        { (success) in
            if success { foundMatch (colour) }
        })
}