我可以在任意 UIView 变量上设置动画吗?

Can I set up an animation on an arbitrary UIView variable?

过去,只要我处理的属性已经是 UIKit 框架的一部分,我就很好地使用了 UIView 动画。

最近,我创建了一个显示某些 calendar/scheduling 行为并支持无限滚动的自定义 UIView 控件。控制滚动位置的是一个简单的 NSDate 变量,我已将其声明为:

var position = NSDate().mondayMorning() {
    didSet {
        self.setNeedsDisplay()
    }
}

只要 position 发生变化,一切都会正常进行。使用 UIPanGestureRecognizer:

设置滚动甚至很简单
struct StartState { static var position:NSDate = NSDate() }
switch pan.state {
case .Began:
    StartState.position = self.position
case .Changed:
    let translation = pan.translationInView(self).y
    self.position = StartState.position - ((7 * 24).hours / self.cellWidth * translation)
case .Cancelled:
    self.position = StartState.position
default:
    break
}

棘手的部分出现在我尝试在 .Ended 情况下实施贴花运动时。理想情况下,我想要某种 UIView.animationWithDuration(... .CurveEaseOut) 咒语,但尽管反复试验,但我没有任何工作。过去,我已经能够像那样做我自己的自定义内容,但在那些情况下,我弄乱了布局,所以我只会让我的动画块成为 layoutIfNeeded,但在这种情况下,我想要沿曲线修改此 NSDate 值并驱动后续显示更新。找不到有用的东西,我只好求助于高中物理并自己做了:

case .Ended:
    let translation = pan.translationInView(self).y
    let v = pan.velocityInView(self).y
    let a:CGFloat = -4000.0 // 4 pixels/millisecond, recommended on gavedev
    let travelTime = (v / a).abs.seconds
    let started = NSDate()
    let timer = Timer()
    timer.interval = 40.milliseconds
    timer.tick = {
        let elapsed = NSDate() - started
        if elapsed >= travelTime {
            timer.stop()
        }
        else {
            let decelDisplacement = (v.abs * CGFloat(elapsed.seconds.magnitude) + (a * 0.5 * CGFloat(elapsed.seconds.magnitude.squared))) * v.sign
            self.position = StartState.position - ((7 * 24).hours / self.cellWidth * (translation + decelDisplacement))
        }
    }
    timer.start()

这行得通。但如果可以在这里利用 CoreAnimation 的东西,我愿意。我可以做到这一点吗?或者动画的东西是全部还是全部?

我还没有找到在不涉及 CoreAnimation 的情况下使用 UIView 动画 API 执行此操作的方法。您当然可以使用 CoreAnimation,Apple 提供了一些 nice example code for this. There's also an objc.io article about this topic

我确实找到了 this solution that works for UIView animations, but it actually underneath accomplishes this behaviour using CoreAnimation,正如 README 中所建议的那样。