|
| 1 | +/* |
| 2 | + Copyright 2017-present The Material Motion Authors. All Rights Reserved. |
| 3 | +
|
| 4 | + Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | + you may not use this file except in compliance with the License. |
| 6 | + You may obtain a copy of the License at |
| 7 | +
|
| 8 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | +
|
| 10 | + Unless required by applicable law or agreed to in writing, software |
| 11 | + distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + See the License for the specific language governing permissions and |
| 14 | + limitations under the License. |
| 15 | + */ |
| 16 | + |
| 17 | +#import "MDMAnimationRegistrar.h" |
| 18 | + |
| 19 | +#import "MDMRegisteredAnimation.h" |
| 20 | + |
| 21 | +@implementation MDMAnimationRegistrar { |
| 22 | + NSMapTable<CALayer *, NSMutableSet<MDMRegisteredAnimation *> *> *_layersToRegisteredAnimation; |
| 23 | +} |
| 24 | + |
| 25 | +- (instancetype)init { |
| 26 | + self = [super init]; |
| 27 | + if (self) { |
| 28 | + _layersToRegisteredAnimation = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsWeakMemory |
| 29 | + valueOptions:NSPointerFunctionsStrongMemory]; |
| 30 | + } |
| 31 | + return self; |
| 32 | +} |
| 33 | + |
| 34 | +#pragma mark - Private |
| 35 | + |
| 36 | +- (void)forEachAnimation:(void (^)(CALayer *, CABasicAnimation *, NSString *))work { |
| 37 | + // Copy the registered animations before iteration in case further modifications happen to the |
| 38 | + // registered animations. Consider if we remove an animation, its associated completion block |
| 39 | + // might invoke logic that adds a new animation, potentially modifying our collections. |
| 40 | + for (CALayer *layer in [_layersToRegisteredAnimation copy]) { |
| 41 | + NSSet *keyPathAnimations = [_layersToRegisteredAnimation objectForKey:layer]; |
| 42 | + for (MDMRegisteredAnimation *keyPathAnimation in [keyPathAnimations copy]) { |
| 43 | + if (![keyPathAnimation.animation isKindOfClass:[CABasicAnimation class]]) { |
| 44 | + continue; |
| 45 | + } |
| 46 | + |
| 47 | + work(layer, [keyPathAnimation.animation copy], keyPathAnimation.key); |
| 48 | + } |
| 49 | + } |
| 50 | +} |
| 51 | + |
| 52 | +#pragma mark - Public |
| 53 | + |
| 54 | +- (void)addAnimation:(CABasicAnimation *)animation |
| 55 | + toLayer:(CALayer *)layer |
| 56 | + forKey:(NSString *)key |
| 57 | + completion:(void(^)(void))completion { |
| 58 | + if (key == nil) { |
| 59 | + key = [NSUUID UUID].UUIDString; |
| 60 | + } |
| 61 | + |
| 62 | + NSMutableSet *animatedKeyPaths = [_layersToRegisteredAnimation objectForKey:layer]; |
| 63 | + if (!animatedKeyPaths) { |
| 64 | + animatedKeyPaths = [[NSMutableSet alloc] init]; |
| 65 | + [_layersToRegisteredAnimation setObject:animatedKeyPaths forKey:layer]; |
| 66 | + } |
| 67 | + MDMRegisteredAnimation *keyPathAnimation = |
| 68 | + [[MDMRegisteredAnimation alloc] initWithKey:key animation:animation]; |
| 69 | + [animatedKeyPaths addObject:keyPathAnimation]; |
| 70 | + |
| 71 | + [CATransaction begin]; |
| 72 | + [CATransaction setCompletionBlock:^{ |
| 73 | + [animatedKeyPaths removeObject:keyPathAnimation]; |
| 74 | + |
| 75 | + if (completion) { |
| 76 | + completion(); |
| 77 | + } |
| 78 | + }]; |
| 79 | + |
| 80 | + [layer addAnimation:animation forKey:key]; |
| 81 | + |
| 82 | + [CATransaction commit]; |
| 83 | +} |
| 84 | + |
| 85 | +- (void)commitCurrentAnimationValuesToAllLayers { |
| 86 | + [self forEachAnimation:^(CALayer *layer, CABasicAnimation *animation, NSString *key) { |
| 87 | + id presentationLayer = [layer presentationLayer]; |
| 88 | + if (presentationLayer != nil) { |
| 89 | + id presentationValue = [presentationLayer valueForKeyPath:animation.keyPath]; |
| 90 | + [layer setValue:presentationValue forKeyPath:animation.keyPath]; |
| 91 | + } |
| 92 | + }]; |
| 93 | +} |
| 94 | + |
| 95 | +- (void)removeAllAnimations { |
| 96 | + [self forEachAnimation:^(CALayer *layer, CABasicAnimation *animation, NSString *key) { |
| 97 | + [layer removeAnimationForKey:key]; |
| 98 | + }]; |
| 99 | + [_layersToRegisteredAnimation removeAllObjects]; |
| 100 | +} |
| 101 | + |
| 102 | +@end |
0 commit comments