|
20 | 20 |
|
21 | 21 | #import <UIKit/UIKit.h>
|
22 | 22 |
|
| 23 | +#pragma mark - Private |
| 24 | + |
| 25 | +static BOOL IsNumberValue(id someValue) { |
| 26 | + return [someValue isKindOfClass:[NSNumber class]]; |
| 27 | +} |
| 28 | + |
| 29 | +static BOOL IsCGPointType(id someValue) { |
| 30 | + if ([someValue isKindOfClass:[NSValue class]]) { |
| 31 | + NSValue *asValue = (NSValue *)someValue; |
| 32 | + const char *objCType = @encode(CGPoint); |
| 33 | + return strncmp(asValue.objCType, objCType, strlen(objCType)) == 0; |
| 34 | + } |
| 35 | + return NO; |
| 36 | +} |
| 37 | + |
| 38 | +static BOOL IsCGSizeType(id someValue) { |
| 39 | + if ([someValue isKindOfClass:[NSValue class]]) { |
| 40 | + NSValue *asValue = (NSValue *)someValue; |
| 41 | + const char *objCType = @encode(CGSize); |
| 42 | + return strncmp(asValue.objCType, objCType, strlen(objCType)) == 0; |
| 43 | + } |
| 44 | + return NO; |
| 45 | +} |
| 46 | + |
| 47 | +#pragma mark - Public |
| 48 | + |
23 | 49 | CABasicAnimation *MDMAnimationFromTiming(MDMMotionTiming timing, CGFloat timeScaleFactor) {
|
24 | 50 | CABasicAnimation *animation;
|
25 | 51 | switch (timing.curve.type) {
|
@@ -67,17 +93,7 @@ void MDMConfigureAnimation(CABasicAnimation *animation,
|
67 | 93 | return; // Nothing to do here.
|
68 | 94 | }
|
69 | 95 |
|
70 |
| - // We can't infer the from/to value types from the animation if the values are NSValue types, so |
71 |
| - // we map known key paths to their data types here: |
72 |
| - static NSSet *sizeKeyPaths = nil; |
73 |
| - static NSSet *positionKeyPaths = nil; |
74 |
| - static dispatch_once_t onceToken; |
75 |
| - dispatch_once(&onceToken, ^{ |
76 |
| - sizeKeyPaths = [NSSet setWithArray:@[@"bounds.size", @"shadowOffset"]]; |
77 |
| - positionKeyPaths = [NSSet setWithArray:@[@"position", @"anchorPoint"]]; |
78 |
| - }); |
79 |
| - |
80 |
| - if ([animation.toValue isKindOfClass:[NSNumber class]]) { |
| 96 | + if (IsNumberValue(animation.toValue)) { |
81 | 97 | // Non-additive animations animate along a direct path between fromValue and toValue, regardless
|
82 | 98 | // of the model layer. Additive animations, on the other hand, animate towards the layer's model
|
83 | 99 | // value by applying this formula:
|
@@ -166,7 +182,7 @@ void MDMConfigureAnimation(CABasicAnimation *animation,
|
166 | 182 | springAnimation.initialVelocity = absoluteInitialVelocity / displacement;
|
167 | 183 | }
|
168 | 184 |
|
169 |
| - } else if ([sizeKeyPaths containsObject:animation.keyPath]) { |
| 185 | + } else if (IsCGSizeType(animation.toValue)) { |
170 | 186 | CGSize from = [animation.fromValue CGSizeValue];
|
171 | 187 | CGSize to = [animation.toValue CGSizeValue];
|
172 | 188 | CGSize additiveDisplacement = CGSizeMake(from.width - to.width, from.height - to.height);
|
@@ -198,7 +214,7 @@ void MDMConfigureAnimation(CABasicAnimation *animation,
|
198 | 214 | springAnimation.initialVelocity = absoluteInitialVelocity / displacement;
|
199 | 215 | }
|
200 | 216 |
|
201 |
| - } else if ([positionKeyPaths containsObject:animation.keyPath]) { |
| 217 | + } else if (IsCGPointType(animation.toValue)) { |
202 | 218 | CGPoint from = [animation.fromValue CGPointValue];
|
203 | 219 | CGPoint to = [animation.toValue CGPointValue];
|
204 | 220 | CGPoint additiveDisplacement = CGPointMake(from.x - to.x, from.y - to.y);
|
|
0 commit comments