@@ -67,7 +67,9 @@ class HeadlessLayerImplicitAnimationTests: XCTestCase {
67
67
layer. opacity = 0.5
68
68
CATransaction . commit ( )
69
69
70
- XCTAssertEqual ( layer. animationKeys ( ) !, [ " opacity " ] )
70
+ let animation = layer. animation ( forKey: " opacity " ) as! CABasicAnimation
71
+ XCTAssertEqual ( animation. keyPath, " opacity " )
72
+ XCTAssertEqual ( animation. duration, 0.5 )
71
73
}
72
74
73
75
func testDoesNotImplicitlyAnimateInCATransactionWithActionsDisabled( ) {
@@ -80,12 +82,43 @@ class HeadlessLayerImplicitAnimationTests: XCTestCase {
80
82
XCTAssertNil ( layer. animationKeys ( ) )
81
83
}
82
84
85
+ func testCATransactionTimingTakesPrecedenceOverUIViewTimingInside( ) {
86
+ UIView . animate ( withDuration: 0.5 ) {
87
+ CATransaction . begin ( )
88
+ CATransaction . setAnimationDuration ( 0.2 )
89
+ self . layer. opacity = 0.5
90
+ CATransaction . commit ( )
91
+ }
92
+
93
+ let animation = layer. animation ( forKey: " opacity " ) as! CABasicAnimation
94
+ XCTAssertEqual ( animation. keyPath, " opacity " )
95
+ XCTAssertEqual ( animation. duration, 0.2 )
96
+ }
97
+
98
+ // Verifies the somewhat counter-intuitive fact that CATransaction's animation duration always
99
+ // takes precedence over UIView's animation duration. This means that animating a headless layer
100
+ // using UIView animation APIs may not result in the expected timings.
101
+ func testCATransactionTimingTakesPrecedenceOverUIViewTimingOutside( ) {
102
+ CATransaction . begin ( )
103
+ CATransaction . setAnimationDuration ( 0.2 )
104
+ UIView . animate ( withDuration: 0.5 ) {
105
+ self . layer. opacity = 0.5
106
+ }
107
+ CATransaction . commit ( )
108
+
109
+ let animation = layer. animation ( forKey: " opacity " ) as! CABasicAnimation
110
+ XCTAssertEqual ( animation. keyPath, " opacity " )
111
+ XCTAssertEqual ( animation. duration, 0.2 )
112
+ }
113
+
83
114
func testDoesImplicitlyAnimateInUIViewAnimateBlock( ) {
84
115
UIView . animate ( withDuration: 0.5 ) {
85
116
self . layer. opacity = 0.5
86
117
}
87
118
88
- XCTAssertEqual ( layer. animationKeys ( ) !, [ " opacity " ] )
119
+ let animation = layer. animation ( forKey: " opacity " ) as! CABasicAnimation
120
+ XCTAssertEqual ( animation. keyPath, " opacity " )
121
+ XCTAssertEqual ( animation. duration, CATransaction . animationDuration ( ) )
89
122
}
90
123
91
124
func testDoesNotImplicitlyAnimateInUIViewAnimateBlockWithActionsDisabledInside( ) {
@@ -110,8 +143,27 @@ class HeadlessLayerImplicitAnimationTests: XCTestCase {
110
143
XCTAssertNil ( layer. animationKeys ( ) )
111
144
}
112
145
146
+ func testAnimatorTimingTakesPrecedenceOverCATransactionTiming( ) {
147
+ let animator = MotionAnimator ( )
148
+ animator. additive = false
149
+ let timing = MotionTiming ( delay: 0 ,
150
+ duration: 1 ,
151
+ curve: MotionCurveMakeBezier ( p1x: 0 , p1y: 0 , p2x: 0 , p2y: 0 ) ,
152
+ repetition: . init( type: . none, amount: 0 , autoreverses: false ) )
153
+
154
+ animator. animate ( with: timing) {
155
+ self . layer. opacity = 0.5
156
+ }
157
+
158
+ let animation = layer. animation ( forKey: " opacity " ) as! CABasicAnimation
159
+ XCTAssertEqual ( animation. keyPath, " opacity " )
160
+ XCTAssertEqual ( animation. duration, timing. duration)
161
+ }
162
+
163
+ // MARK: Deprecated tests.
164
+
165
+ @available ( * , deprecated)
113
166
func testDoesImplicitlyAnimateInCATransactionWithLayerDelegateAlone( ) {
114
- // Delegate will allow us to do implicit animations, but only via the motion animator.
115
167
layer. delegate = MotionAnimator . sharedLayerDelegate ( )
116
168
117
169
CATransaction . begin ( )
@@ -122,8 +174,8 @@ class HeadlessLayerImplicitAnimationTests: XCTestCase {
122
174
XCTAssertEqual ( layer. animationKeys ( ) !, [ " opacity " ] )
123
175
}
124
176
177
+ @available ( * , deprecated)
125
178
func testDoesNotImplicitlyAnimateInCATransactionWithLayerDelegateAloneAndActionsAreDisabled( ) {
126
- // Delegate will allow us to do implicit animations, but only via the motion animator.
127
179
layer. delegate = MotionAnimator . sharedLayerDelegate ( )
128
180
129
181
CATransaction . begin ( )
@@ -135,8 +187,8 @@ class HeadlessLayerImplicitAnimationTests: XCTestCase {
135
187
XCTAssertNil ( layer. animationKeys ( ) )
136
188
}
137
189
190
+ @available ( * , deprecated)
138
191
func testDoesImplicitlyAnimateInUIViewAnimateBlockWithLayerDelegateAlone( ) {
139
- // Delegate will allow us to do implicit animations, but only via the motion animator.
140
192
layer. delegate = MotionAnimator . sharedLayerDelegate ( )
141
193
142
194
UIView . animate ( withDuration: 0.5 ) {
@@ -146,6 +198,7 @@ class HeadlessLayerImplicitAnimationTests: XCTestCase {
146
198
XCTAssertEqual ( layer. animationKeys ( ) !, [ " opacity " ] )
147
199
}
148
200
201
+ @available ( * , deprecated)
149
202
func testDoesImplicitlyAnimateWithLayerDelegateAndAnimator( ) {
150
203
layer. delegate = MotionAnimator . sharedLayerDelegate ( )
151
204
0 commit comments