facebookarchive / pop

An extensible iOS and OS X animation library, useful for physics-based interactions.
Other
19.66k stars 2.88k forks source link

Calling pop_removeAllAnimations doesn't work when using same animation on two layers #360

Open josipbernat opened 7 years ago

josipbernat commented 7 years ago

When you try to use same POPBasicAnimation on two CATextLayers and then you call pop_removeAllAnimations on both layers then first layer will still have animation and POPAnimator won't disable CADisplayLink. This results in using CPU without having animations.

In example:

// Somewhere in View:
POPBasicAnimation *opacityAnimation1 = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity];
    opacityAnimation1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];;
    opacityAnimation1.toValue = @(!self.leftTimeLayer.hidden ? 1.0f : 0.0f);
    opacityAnimation1.duration = [CMScrolloramaTableViewCell animationDuration:duration];
    opacityAnimation1.removedOnCompletion = YES;
    [opacityAnimation1 setCompletionBlock:^(POPAnimation *anim, BOOL finished) {

        if (finished) {
            if (self.leftTimeLayer.opacity < 0.1f) {
                self.leftTimeLayer.hidden = YES;
            }
            if (self.rightTimeLayer.opacity < 0.1f) {
                self.rightTimeLayer.hidden = YES;
            }
        }
    }];

//And then in dealloc
    [_leftTimeLayer pop_removeAllAnimations];
    [_rightTimeLayer pop_removeAllAnimations];

//Inside POPAnimator.mm
static void updateDisplayLink(POPAnimator *self) {
    BOOL paused = (0 == self->_observers.count && self->_list.empty()) || self->_disableDisplayLink;
//  paused is always YES because _list isn't empty. It contains leftTimeLayer reference.
}

Workaround for this is to create 2 animations but that doubles the code and opens door for bugs. I'm using version 1.0.9 from cocoapods