Working With Keyframes
Where Type Safety Gets in the Way
Working with advanced animations is always a bit of a challenge, and when working on a keyframe based animation, I couldn't figure out how to get the entire animation to run in a linear fashion, and it took some digging on Stack Overflow to get on the right track. Without type safety the answer was to add the UIViewAnimationOption
value to the UIViewKeyframeAnimationOption
value. With type safety, it takes getting clever with raw values.
First I checked if all of the UIViewAnimationOption
flags were supported by keyframe animations, at at a glance it looks like the answer is that some of them are ignored if applied to a keyframe animation. That meant that just writing an initializer that crammed to two values together wasn't a great plan.
After a bit of digging, I ended up writing this:
public extension UIViewKeyframeAnimationOptions {
// This exists because keyframe options doesn't expose the easing for the overall curve
public init(keyframeAnimationsOptions: UIViewKeyframeAnimationOptions, animationCurve: UIViewAnimationCurve) {
let animationOptions: UIViewAnimationOptions
switch animationCurve {
case .EaseIn: animationOptions = .CurveEaseIn
case .EaseInOut: animationOptions = .CurveEaseInOut
case .EaseOut: animationOptions = .CurveEaseOut
case .Linear: animationOptions = .CurveLinear
}
self = UIViewKeyframeAnimationOptions(rawValue: keyframeAnimationsOptions.rawValue | animationOptions.rawValue)
}
}
That consumes a UIViewKeyframeAnimationOption
and a UIViewAnimationCurve
value, and inserts the correct value for the animation curve into the UIViewKeyframeAnimationOption
set. It's still mashing raw values together under the hood, there's no getting around that, but that's well encapsulated and only valid sets of raw values can be mashed together.