From 8be151c06d3769540a5efce9d9f00bbc7e6f1555 Mon Sep 17 00:00:00 2001 From: featherless Date: Thu, 2 Nov 2017 16:33:04 -0400 Subject: [PATCH] Disable implicit animations when adding explicit animations in the animator (#20) * Disable implicit animations when adding explicit animations in the animator. A client using the animator expects that it will only add animations for the key path that was specified, but it's possible that setting the final value for a given key path can create implicit animations. We now disable implicit animations when setting the final value to the layer. * Remove unnecessary state. --- src/MDMMotionAnimator.m | 3 +++ tests/unit/MotionAnimatorTests.swift | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/MDMMotionAnimator.m b/src/MDMMotionAnimator.m index a1056ac..ec5c150 100644 --- a/src/MDMMotionAnimator.m +++ b/src/MDMMotionAnimator.m @@ -112,7 +112,10 @@ - (void)animateWithTiming:(MDMMotionTiming)timing } } + [CATransaction begin]; + [CATransaction setDisableActions:YES]; [layer setValue:[values lastObject] forKeyPath:keyPath]; + [CATransaction commit]; } - (void)addCoreAnimationTracer:(void (^)(CALayer *, CAAnimation *))tracer { diff --git a/tests/unit/MotionAnimatorTests.swift b/tests/unit/MotionAnimatorTests.swift index 21e5d4a..86199c0 100644 --- a/tests/unit/MotionAnimatorTests.swift +++ b/tests/unit/MotionAnimatorTests.swift @@ -47,5 +47,27 @@ class MotionAnimatorTests: XCTestCase { XCTAssertTrue(true) } + func testAnimatorOnlyAddsAnimationsForKeyPath() { + let animator = MotionAnimator() + let timing = MotionTiming(delay: 0, + duration: 1, + curve: .init(type: .bezier, data: (0, 0, 0, 0)), + repetition: .init(type: .none, amount: 0, autoreverses: false)) + + let window = UIWindow() + window.makeKeyAndVisible() + let view = UIView() // Need to animate a view's layer to get implicit animations. + window.addSubview(view) + + XCTAssertEqual(view.layer.delegate as? UIView, view) + + UIView.animate(withDuration: 0.5) { + animator.animate(with: timing, to: view.layer, withValues: [0, 1], keyPath: .rotation) + + // Setting transform.rotation.z will create an implicit transform if implicit animations + // aren't disabled by the animator properly, so verify that such an animation doesn't exist: + XCTAssertNil(view.layer.animation(forKey: "transform")) + } + } }