Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up unnecessarily and unintentionally slow waitForAnimationsToFinish calls #1301

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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