Skip to content

Commit

Permalink
Merge pull request #1301 from justinseanmartin/jmartin/long-animations
Browse files Browse the repository at this point in the history
Speed up unnecessarily and unintentionally slow `waitForAnimationsToFinish` calls
  • Loading branch information
Justin Martin authored Sep 24, 2024
2 parents ec9b38d + 27d9ff1 commit 8f094a6
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 19 deletions.
1 change: 1 addition & 0 deletions Sources/KIF/Additions/CALayer-KIFAdditions.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
@abstract Calls a block on the layer itself and on all its descendent layers.
@param block The block that will be called on the layers. Stop the traversation
of the layers by assigning YES to the stop-parameter of the block.
We will not recurse into hidden layers.
*/
- (void)performBlockOnDescendentLayers:(void (^)(CALayer *layer, BOOL *stop))block;

Expand Down
48 changes: 29 additions & 19 deletions Sources/KIF/Additions/CALayer-KIFAdditions.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,31 @@ - (BOOL)hasAnimations
{
__block BOOL result = NO;
[self performBlockOnDescendentLayers:^(CALayer *layer, BOOL *stop) {
// explicitly exclude _UIParallaxMotionEffect as it is used in alertviews, and we don't want every alertview to be paused
// explicitly exclude UITextSelectionViewCaretBlinkAnimation as it is used in textfields, and we don't want every view with textfields to be paused
BOOL hasAnimation = layer.animationKeys.count != 0 && ![layer.animationKeys containsObject:@"_UIParallaxMotionEffect"] && ![layer.animationKeys containsObject:@"UITextSelectionViewCaretBlinkAnimation"];
if (hasAnimation && !layer.hidden) {
double currentTime = CACurrentMediaTime() * [layer KIF_absoluteSpeed];

[layer.animationKeys enumerateObjectsUsingBlock:^(NSString *animationKey, NSUInteger idx, BOOL *innerStop) {
CAAnimation *animation = [layer animationForKey:animationKey];
double beginTime = [animation beginTime];
double completionTime = [animation KIF_completionTime];

// Ignore infinitely repeating animations
if (currentTime >= beginTime && completionTime != HUGE_VALF && currentTime < completionTime) {
result = YES;
*innerStop = YES;
*stop = YES;
}
}];
}
// explicitly exclude _UIParallaxMotionEffect as it is used in alertviews, and we don't want every alertview to be paused
// explicitly exclude UITextSelectionViewCaretBlinkAnimation as it is used in textfields, and we don't want every view with textfields to be paused
BOOL hasAnimation = layer.animationKeys.count != 0 && ![layer.animationKeys containsObject:@"_UIParallaxMotionEffect"] && ![layer.animationKeys containsObject:@"UITextSelectionViewCaretBlinkAnimation"];

// Ignore the animation of the KIF touch visualizer circle as it does not affect any view behavior
if ([NSStringFromClass(layer.delegate.class) isEqualToString:@"KIFTouchVisualizerView"]) {
hasAnimation = NO;
}

if (hasAnimation && !layer.hidden) {
double currentTime = CACurrentMediaTime() * [layer KIF_absoluteSpeed];

[layer.animationKeys enumerateObjectsUsingBlock:^(NSString *animationKey, NSUInteger idx, BOOL *innerStop) {
CAAnimation *animation = [layer animationForKey:animationKey];
double beginTime = [animation beginTime];
double completionTime = [animation KIF_completionTime];

// Ignore long running animations (> 1 minute duration)
if (currentTime >= beginTime && completionTime < currentTime + 60 && currentTime < completionTime) {
result = YES;
*innerStop = YES;
*stop = YES;
}
}];
}
}];
return result;
}
Expand All @@ -58,6 +64,10 @@ - (void)performBlockOnDescendentLayers:(void (^)(CALayer *layer, BOOL *stop))blo

- (void)performBlockOnDescendentLayers:(void (^)(CALayer *, BOOL *))block stop:(BOOL *)stop
{
if (self.isHidden) {
return;
}

block(self, stop);
if (*stop) {
return;
Expand Down

0 comments on commit 8f094a6

Please sign in to comment.