简体   繁体   English

动画无法正常运行(Swift 3)

[英]Animation not working properly (Swift 3)

The following block is my code. 以下块是我的代码。 I don't know why, but the animation delay is not working at all. 我不知道为什么,但是动画延迟根本不起作用。 No matter how many seconds I increase it to be.. 不管我增加多少秒。

func changeLabelisTapped(_ textLabel: UILabel, tapGesture: UITapGestureRecognizer) {
    for i in 0...2{
        UIView.animate(withDuration: 2, delay: Double(i)+2, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseOut, animations: ({
            self.subArray.remove(at: 0)
            self.collectionView.deleteItems(at: [IndexPath(row: 0, section: 0)])
        }), completion: nil)
    }
    let tempArray = Array(self.tabledData[3...self.tabledData.count-1])
    print(tempArray.count)
    for j in 0...2{
        UIView.animate(withDuration: 2, delay: 2, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseOut, animations: ({
            let newElement = tempArray[j]
            self.subArray.append(newElement)
            self.collectionView.insertItems(at:[IndexPath(row: j, section: 0)])
        }), completion: nil)
    }
}

UIView animations do not queue. UIView动画不会排队。 So everytime you process it through a loop the next animations cancels the one before and you do not see the delay. 因此,每次通过循环处理时,下一个动画都会取消之前的动画,并且看不到延迟。 Instead of using a loop you should chain your animations so that the next one is called in the completion handler. 而不是使用循环,您应该链接动画,以便在完成处理程序中调用下一个动画。 Remove the loop and call the next animation to occur in the completion handler. 删除循环,并调用下一个动画在完成处理程序中发生。

    var currentCount = 0

    UIView.animate(withDuration: 2, delay: 2, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseOut, animations: ({
        let newElement = tempArray[self.currentCount]
        self.subArray.append(newElement)
        self.collectionView.insertItems(at:[IndexPath(row: self.currentCount, section: 0)])
    }), completion: { _ in
       //next animation follows here 
       self.currentCount += 1
         UIView.animate(withDuration: 2, delay: 2, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseOut, animations: ({
        let newElement = tempArray[self.currentCount]
        self.subArray.append(newElement)
        self.collectionView.insertItems(at:[IndexPath(row: self.currentCount, section: 0)])
    }), completion: { _ in //and so on

     })

    }) 

If you want to cleanly control how many times the animation should happen, then you can use a recursive callback in the completion handler. 如果要完全控制动画应发生的次数,则可以在完成处理程序中使用递归回调。 To make this work, move your animation code into a function. 为此,请将动画代码移到一个函数中。

    let loopCount = 3

    var currentCount = 0

    func animateMyLabel() {
    UIView.animate(withDuration: 2, delay: 2, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseOut, animations: ({
        let newElement = tempArray[self.currentCount]
        self.subArray.append(newElement)
        self.collectionView.insertItems(at:[IndexPath(row: self.currentCount, section: 0)])
    }), completion: { _ in 
        if self.currentCount < self.loopCount {
          self.currentCount += 1
          //call the animation again
          self.animateMyLabel()
        }

    })

    }

EDIT 编辑

Having faced a similar delay issue in a current project I am doing, I have learnt a new way to force a delay if it is not working as expected which might help anyone that comes across this question. 在我正在执行的当前项目中遇到了类似的延迟问题,我学会了一种新的方法来强制延迟(如果延迟未按预期工作),这可能会帮助遇到此问题的任何人。 The solution is to force a delay in the completion handler just before the next animation should occur by adding delay(seconds: n) { } where n is the number of seconds the delay should happen for. 解决方案是通过添加delay(seconds:n){}强制在完成处理程序中延迟一个延迟,其中n是延迟发生的秒数。 So to add this to the problem: 因此,将其添加到问题中:

   let loopCount = 3

    var currentCount = 0

    func animateMyLabel() {
    UIView.animate(withDuration: 2, delay: 2, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseOut, animations: ({
        let newElement = tempArray[self.currentCount]
        self.subArray.append(newElement)
        self.collectionView.insertItems(at:[IndexPath(row: self.currentCount, section: 0)])
    }), completion: { _ in 
        if self.currentCount < self.loopCount {
          //add the delay here
          delay(seconds: 2) {
          self.currentCount += 1
          //call the animation again
          self.animateMyLabel()
          }
        }

    })

    }

Furthermore, although animations do not queue, it is possible to use a loop for an animation provided the next animation in sequence has a delay which allows the previous animation to complete. 此外,尽管动画没有排队,但如果顺序播放的下一个动画具有一定的延迟,则可以对动画使用循环,以使上一个动画完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM