├── .gitignore
├── .gitmodules
├── .travis.yml
├── CFAAction.podspec
├── CFAAction.xcodeproj
├── project.pbxproj
└── xcshareddata
│ └── xcschemes
│ ├── CFAAction-iOS.xcscheme
│ └── CFAAction.xcscheme
├── CFAAction
├── CFAAction+Private.h
├── CFAAction-Info.plist
├── CFAAction-Prefix.pch
├── CFAAction.h
├── CFAAction.m
├── CFACustomAction.h
├── CFACustomAction.m
├── CFAFade.h
├── CFAFade.m
├── CFAFollowPath.h
├── CFAFollowPath.m
├── CFAGroup.h
├── CFAGroup.m
├── CFAHide.h
├── CFAHide.m
├── CFAMove.h
├── CFAMove.m
├── CFAPerformSelector.h
├── CFAPerformSelector.m
├── CFARepeat.h
├── CFARepeat.m
├── CFAResize.h
├── CFAResize.m
├── CFARotate.h
├── CFARotate.m
├── CFARunBlock.h
├── CFARunBlock.m
├── CFAScale.h
├── CFAScale.m
├── CFASequence.h
├── CFASequence.m
├── CFASpeed.h
├── CFASpeed.m
├── CFAWait.h
├── CFAWait.m
├── NSBezierPath+CFABezierPathQuartzAssistant.h
├── NSBezierPath+CFABezierPathQuartzAssistant.m
└── en.lproj
│ └── InfoPlist.strings
├── CFAActionTests
├── CFAActionSpec.m
├── CFAActionTests-Info.plist
├── CFAActionTests-Prefix.pch
├── CFAPerformSelectorSpec.m
├── CFARunBlockSpec.m
├── CFATestLayer.h
├── CFATestLayer.m
└── en.lproj
│ └── InfoPlist.strings
├── Example
└── CAActionDemo
│ ├── CAActionDemo.xcodeproj
│ └── project.pbxproj
│ └── CAActionDemo
│ ├── Base.lproj
│ └── MainMenu.xib
│ ├── CAActionDemo-Info.plist
│ ├── CAActionDemo-Prefix.pch
│ ├── CFIAppDelegate.h
│ ├── CFIAppDelegate.m
│ ├── Images.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
│ ├── en.lproj
│ ├── Credits.rtf
│ └── InfoPlist.strings
│ └── main.m
├── LICENSE.md
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | .DS_Store
3 | */build/*
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | *.xcworkspace
13 | !default.xcworkspace
14 | xcuserdata
15 | profile
16 | *.moved-aside
17 | DerivedData
18 | .idea/
19 | *.hmap
20 | *.xcuserstate
21 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "External/Expecta"]
2 | path = External/Expecta
3 | url = https://github.com/specta/expecta.git
4 | [submodule "External/Specta"]
5 | path = External/Specta
6 | url = https://github.com/specta/specta.git
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | osx_image: xcode7.3
3 |
4 | script:
5 | - set -o pipefail
6 | - xcodebuild test -scheme CFAAction | xcpretty -c
7 | - xcodebuild build -scheme CFAAction-iOS -destination 'platform=iOS Simulator,name=iPad Pro' | xcpretty -c
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/CFAAction.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "CFAAction"
3 | s.version = "0.1.0"
4 | s.summary = "Composable Core Animation Actions à la SceneKit"
5 | s.homepage = "https://github.com/CodaFi/CFAAction"
6 | s.license = { :type => "MIT", :text => <<-LICENSE
7 | The MIT License (MIT)
8 |
9 | Copyright (c) 2015-2016 Robert Widmann
10 |
11 | Permission is hereby granted, free of charge, to any person obtaining a copy
12 | of this software and associated documentation files (the "Software"), to deal
13 | in the Software without restriction, including without limitation the rights
14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | copies of the Software, and to permit persons to whom the Software is
16 | furnished to do so, subject to the following conditions:
17 |
18 | The above copyright notice and this permission notice shall be included in all
19 | copies or substantial portions of the Software.
20 |
21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | SOFTWARE.
28 |
29 | LICENSE
30 | }
31 | s.authors = { "CodaFi" => "devteam.codafi@gmail.com" }
32 |
33 | s.requires_arc = true
34 | s.osx.deployment_target = "10.8"
35 | s.ios.deployment_target = "7.0"
36 | s.source = { :git => "https://github.com/CodaFi/CFAAction.git", :tag => "v#{s.version}", :submodules => true }
37 | s.source_files = "CFAAction/*.{h,m}"
38 | end
39 |
40 |
--------------------------------------------------------------------------------
/CFAAction.xcodeproj/xcshareddata/xcschemes/CFAAction-iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
56 |
57 |
63 |
64 |
65 |
66 |
67 |
68 |
74 |
75 |
77 |
78 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/CFAAction.xcodeproj/xcshareddata/xcschemes/CFAAction.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
55 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
74 |
76 |
77 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/CFAAction/CFAAction+Private.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFAAction_Private.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction.h"
11 |
12 | @interface CFAAction ()
13 |
14 | @property (nonatomic) BOOL finished;
15 | @property (NS_NONATOMIC_IOSONLY) float repeatCount;
16 | @property (nonatomic) CAMediaTimingFunction *timingFunction;
17 |
18 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time;
19 | - (void)setOnCompletion:(void(^)(void))block;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/CFAAction/CFAAction-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | FMWK
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | NSHumanReadableCopyright
26 | Copyright © 2013 CodaFi. All rights reserved.
27 | NSPrincipalClass
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/CFAAction/CFAAction-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header
3 | //
4 | // The contents of this file are implicitly included at the beginning of every source file.
5 | //
6 |
7 | #define OBJC_OLD_DISPATCH_PROTOTYPES 0
8 |
9 | #ifdef __OBJC__
10 | #import
11 | #endif
12 |
--------------------------------------------------------------------------------
/CFAAction/CFAAction.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFAAction.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import
11 |
12 | /// The modes that an action can use to adjust the apparent timing of the action.
13 | typedef NS_ENUM(NSInteger, CFAActionTimingMode) {
14 | /// Specifies linear pacing. Linear pacing causes an animation to occur evenly over its duration.
15 | CFAActionTimingLinear,
16 | /// Specifies ease-in pacing. Ease-in pacing causes the animation to begin slowly, and then
17 | /// speed up as it progresses.
18 | CFAActionTimingEaseIn,
19 | /// Specifies ease-out pacing. Ease-out pacing causes the animation to begin quickly, and then
20 | /// slow as it completes.
21 | CFAActionTimingEaseOut,
22 | /// Specifies ease-in ease-out pacing. An ease-in ease-out animation begins slowly, accelerates
23 | /// through the middle of its duration, and then slows again before completing.
24 | CFAActionTimingEaseInEaseOut
25 | };
26 |
27 | NS_ASSUME_NONNULL_BEGIN
28 |
29 | /// A CFAAction is an action that is executed on a layer. Actions are most often used to change the
30 | /// structure and appearance of layers, but can also be used to make other changes to the layer tree,
31 | /// or execute custom actions.
32 | ///
33 | /// Most actions allow you to change a layer's properties such as its position, rotation, or scale.
34 | /// When an action is animated, the duration property states how long the action takes to complete in
35 | /// seconds, and its timing mode property determines the rate at which the animation executes.
36 | ///
37 | /// Many actions can be reversed, allowing you to create another action object that reverses the
38 | /// effect of that action. Actions that cannot be reversed will often return the same action, or a
39 | /// copy of the original.
40 | ///
41 | /// Some actions include other actions as children:
42 | ///
43 | /// - A sequence action has multiple child actions. Each action in the sequence begins after the
44 | /// previous action ends.
45 | /// - A group action has multiple child actions. All actions stored in the group begin executing at
46 | /// the same time.
47 | /// - A repeating action stores a single child action. When the child action completes, it is
48 | /// restarted.
49 | /// - Groups, sequences, and repeating actions can be nested. The ability to combine actions together
50 | /// allows you to add very sophisticated behaviors to a node.
51 | ///
52 | @interface CFAAction : NSObject
53 |
54 | /// The duration required to complete an action.
55 | @property (NS_NONATOMIC_IOSONLY) NSTimeInterval duration;
56 |
57 | /// The timing mode used to execute an action.
58 | @property (NS_NONATOMIC_IOSONLY) CFAActionTimingMode timingMode;
59 |
60 | /// A speed factor that modifies how fast an action runs.
61 | @property (NS_NONATOMIC_IOSONLY) CGFloat speed;
62 |
63 | /// Creates an action that reverses the behavior of another action.
64 | - (CFAAction *)reversedAction;
65 |
66 | @end
67 |
68 | @interface CFAAction (CFAActions)
69 |
70 |
71 | #pragma mark - Move Actions
72 |
73 |
74 | /// Creates an action that moves a node relative to its current position.
75 | + (CFAAction *)moveByX:(CGFloat)deltaX y:(CGFloat)deltaY duration:(NSTimeInterval)sec;
76 |
77 | #if CGVECTOR_DEFINED
78 | /// Creates an action that moves a node relative to its current position.
79 | + (CFAAction *)moveBy:(CGVector)delta duration:(NSTimeInterval)sec;
80 | #endif
81 |
82 | /// Creates an action that moves a node to a new position.
83 | + (CFAAction *)moveTo:(CGPoint)location duration:(NSTimeInterval)sec;
84 |
85 | /// Creates an action that moves a node horizontally.
86 | + (CFAAction *)moveToX:(CGFloat)x duration:(NSTimeInterval)sec;
87 |
88 | /// Creates an action that moves a node vertically.
89 | + (CFAAction *)moveToY:(CGFloat)y duration:(NSTimeInterval)sec;
90 |
91 | /// Creates an action that moves the node along a relative path, orienting the node to the path.
92 | + (CFAAction *)followPath:(CGPathRef)path duration:(NSTimeInterval)sec;
93 |
94 | /// Creates an action that moves the node along a path.
95 | + (CFAAction *)followPath:(CGPathRef)path asOffset:(BOOL)offset orientToPath:(BOOL)orient duration:(NSTimeInterval)sec;
96 |
97 |
98 | #pragma mark - Rotate Actions
99 |
100 |
101 | /// Creates an action that rotates the node by a relative value.
102 | + (CFAAction *)rotateByAngle:(CGFloat)radians duration:(NSTimeInterval)sec;
103 |
104 | /// Creates an action that rotates the node counterclockwise to an absolute angle.
105 | + (CFAAction *)rotateToAngle:(CGFloat)radians duration:(NSTimeInterval)sec;
106 |
107 | /// Creates an action that rotates the node to an absolute value.
108 | + (CFAAction *)rotateToAngle:(CGFloat)radians duration:(NSTimeInterval)sec shortestUnitArc:(BOOL)shortestUnitArc;
109 |
110 |
111 | #pragma mark - Transparency Actions
112 |
113 |
114 | /// Creates an action that changes the alpha value of the node to 1.0.
115 | + (CFAAction *)fadeInWithDuration:(NSTimeInterval)sec;
116 |
117 | /// Creates an action that changes the alpha value of the node to 0.0.
118 | + (CFAAction *)fadeOutWithDuration:(NSTimeInterval)sec;
119 |
120 | /// Creates an action that adjusts the alpha value of a node by a relative value.
121 | + (CFAAction *)fadeAlphaBy:(CGFloat)factor duration:(NSTimeInterval)sec;
122 |
123 | /// Creates an action that adjusts the alpha value of a node to a new value.
124 | + (CFAAction *)fadeAlphaTo:(CGFloat)alpha duration:(NSTimeInterval)sec;
125 |
126 |
127 | #pragma mark - Resize Actions
128 |
129 |
130 | /// Creates an action that adjusts the size of a sprite.
131 | + (CFAAction *)resizeByWidth:(CGFloat)width height:(CGFloat)height duration:(NSTimeInterval)duration;
132 |
133 | /// Creates an action that changes the width and height of a sprite to a new absolute value.
134 | + (CFAAction *)resizeToWidth:(CGFloat)width height:(CGFloat)height duration:(NSTimeInterval)duration;
135 |
136 | /// Creates an action that changes the width of a sprite to a new absolute value.
137 | + (CFAAction *)resizeToWidth:(CGFloat)width duration:(NSTimeInterval)duration;
138 |
139 | /// Creates an action that changes the height of a sprite to a new absolute value.
140 | + (CFAAction *)resizeToHeight:(CGFloat)height duration:(NSTimeInterval)duration;
141 |
142 |
143 | #pragma mark - Scale Actions
144 |
145 |
146 | /// Creates an action that changes the x and y scale values of a node by a relative value.
147 | + (CFAAction *)scaleBy:(CGFloat)scale duration:(NSTimeInterval)sec;
148 |
149 | /// Creates an action that adds relative values to the x and y scale values of a node.
150 | + (CFAAction *)scaleXBy:(CGFloat)xScale y:(CGFloat)yScale duration:(NSTimeInterval)sec;
151 |
152 | /// Creates an action that changes the x and y scale values of a node.
153 | + (CFAAction *)scaleTo:(CGFloat)scale duration:(NSTimeInterval)sec;
154 |
155 | /// Creates an action that changes the x and y scale values of a node.
156 | + (CFAAction *)scaleXTo:(CGFloat)xScale y:(CGFloat)yScale duration:(NSTimeInterval)sec;
157 |
158 | /// Creates an action that changes the x scale value of a node to a new value.
159 | + (CFAAction *)scaleXTo:(CGFloat)scale duration:(NSTimeInterval)sec;
160 |
161 | /// Creates an action that changes the y scale value of a node to a new value.
162 | + (CFAAction *)scaleYTo:(CGFloat)scale duration:(NSTimeInterval)sec;
163 |
164 | #pragma mark - Show or Hide Actions
165 |
166 | /// Creates an action that hides a node.
167 | + (CFAAction *)hide;
168 |
169 | /// Creates an action that unhides a node.
170 | + (CFAAction *)unhide;
171 |
172 |
173 | #pragma mark - Combine Actions
174 |
175 |
176 | /// Creates an action that runs a collection of actions sequentially.
177 | + (CFAAction *)sequence:(NSArray *)actions;
178 |
179 | /// Creates an action that runs a collection of actions in parallel.
180 | + (CFAAction *)group:(NSArray *)actions;
181 |
182 |
183 | #pragma mark - Repeat Actions
184 |
185 |
186 | /// Creates an action that repeats another action a specified number of times.
187 | + (CFAAction *)repeatAction:(CFAAction *)action count:(NSUInteger)count;
188 |
189 | /// Creates an action that repeats another action forever.
190 | + (CFAAction *)repeatActionForever:(CFAAction *)action;
191 |
192 |
193 | #pragma mark - Speed Actions
194 |
195 |
196 | /// Creates an action that changes how fast the node executes actions by a relative value.
197 | + (CFAAction *)speedBy:(CGFloat)speed duration:(NSTimeInterval)sec;
198 |
199 | /// Creates an action that changes how fast the node executes actions.
200 | + (CFAAction *)speedTo:(CGFloat)speed duration:(NSTimeInterval)sec;
201 |
202 |
203 | #pragma mark - Delay Actions
204 |
205 |
206 | /// Creates an action that idles for a specified period of time.
207 | + (CFAAction *)waitForDuration:(NSTimeInterval)sec;
208 |
209 | /// Creates an action that idles for a randomized period of time.
210 | + (CFAAction *)waitForDuration:(NSTimeInterval)sec withRange:(NSTimeInterval)durationRange;
211 |
212 |
213 | #pragma mark - Custom Actions
214 |
215 |
216 | /// Creates an action that calls a method on an object.
217 | + (CFAAction *)performSelector:(SEL)selector onTarget:(id)target;
218 |
219 | /// Creates an action that executes a block.
220 | + (CFAAction *)runBlock:(dispatch_block_t)block;
221 |
222 | /// Creates an action that executes a block on a specific dispatch queue.
223 | + (CFAAction *)runBlock:(dispatch_block_t)block queue:(dispatch_queue_t)queue;
224 |
225 | /// Creates an action that executes a block over a duration.
226 | + (CFAAction *)customActionWithDuration:(NSTimeInterval)seconds actionBlock:(void (^)(CALayer *node, CGFloat elapsedTime))block;
227 |
228 | @end
229 |
230 | @interface CALayer (CFAAction)
231 |
232 | /// Adds an action to the list of actions executed by the node.
233 | - (void)cfa_runAction:(CFAAction *)action;
234 |
235 | /// Adds an action to the list of actions executed by the node. Your block is called when the action
236 | /// completes.
237 | - (void)cfa_runAction:(CFAAction *)action completion:(void (^)(void))block;
238 |
239 | @end
240 |
241 | NS_ASSUME_NONNULL_END
242 |
--------------------------------------------------------------------------------
/CFAAction/CFAAction.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFAAction.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 | #import "CFARunBlock.h"
12 | #import "CFASequence.h"
13 | #import "CFAGroup.h"
14 | #import "CFAHide.h"
15 | #import "CFACustomAction.h"
16 | #import "CFAFade.h"
17 | #import "CFAFollowPath.h"
18 | #import "CFAMove.h"
19 | #import "CFAPerformSelector.h"
20 | #import "CFARotate.h"
21 | #import "CFAResize.h"
22 | #import "CFARepeat.h"
23 | #import "CFAScale.h"
24 | #import "CFASpeed.h"
25 | #import "CFAWait.h"
26 |
27 | @implementation CFAAction {
28 | BOOL _finished;
29 | void (^_completionBlock)(void);
30 | }
31 |
32 | - (id)copyWithZone:(NSZone *)zone {
33 | CFAAction *copyAction = [[self.class alloc] init];
34 | copyAction.duration = self.duration;
35 | copyAction.timingMode = self.timingMode;
36 | copyAction.speed = self.speed;
37 |
38 | return copyAction;
39 | }
40 |
41 | - (CFAAction *)reversedAction {
42 | return [self copy];
43 | }
44 |
45 | // Override point for subclasses
46 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time { }
47 |
48 | - (void)setOnCompletion:(void(^)(void))block {
49 | _completionBlock = [block copy];
50 | }
51 |
52 | - (void)setFinished:(BOOL)finished {
53 | if (finished && _completionBlock) {
54 | _completionBlock();
55 | }
56 | _finished = finished;
57 | }
58 |
59 | - (CAMediaTimingFunction *)timingFunction {
60 | return [CAMediaTimingFunction functionWithName:CFAMediaTimingFunctionName[self.timingMode]];
61 | }
62 |
63 | static NSString * CFAMediaTimingFunctionName[4] = {
64 | @"linear", // CFAActionTimingLinear
65 | @"easeIn", // CFAActionTimingEaseIn
66 | @"easeOut", // CFAActionTimingEaseOut
67 | @"easeInOut" // CFAActionTimingEaseInEaseOut
68 | };
69 |
70 | @end
71 |
72 | @implementation CFAAction (CFAActions)
73 |
74 | + (CFAAction *)moveByX:(CGFloat)deltaX y:(CGFloat)deltaY duration:(NSTimeInterval)sec {
75 | return [CFAMove moveByX:deltaX y:deltaY duration:sec];
76 | }
77 |
78 | #if CGVECTOR_DEFINED
79 | + (CFAAction *)moveBy:(CGVector)delta duration:(NSTimeInterval)sec {
80 | return [CFAMove moveBy:delta duration:sec];
81 | }
82 | #endif
83 |
84 | + (CFAAction *)moveTo:(CGPoint)location duration:(NSTimeInterval)sec {
85 | return [CFAMove moveTo:location duration:sec];
86 | }
87 |
88 | + (CFAAction *)moveToX:(CGFloat)x duration:(NSTimeInterval)sec {
89 | return [CFAMove moveToX:x duration:sec];
90 | }
91 |
92 | + (CFAAction *)moveToY:(CGFloat)y duration:(NSTimeInterval)sec {
93 | return [CFAMove moveToY:y duration:sec];
94 | }
95 |
96 | + (CFAAction *)rotateByAngle:(CGFloat)radians duration:(NSTimeInterval)sec {
97 | return [CFARotate rotateByAngle:radians duration:sec];
98 | }
99 |
100 | + (CFAAction *)rotateToAngle:(CGFloat)radians duration:(NSTimeInterval)sec {
101 | return [CFARotate rotateToAngle:radians duration:sec];
102 | }
103 |
104 | + (CFAAction *)rotateToAngle:(CGFloat)radians duration:(NSTimeInterval)sec shortestUnitArc:(BOOL)shortestUnitArc {
105 | return [CFARotate rotateToAngle:radians duration:sec shortestUnitArc:shortestUnitArc];
106 | }
107 |
108 | + (CFAAction *)resizeByWidth:(CGFloat)width height:(CGFloat)height duration:(NSTimeInterval)duration {
109 | return [CFAResize resizeByWidth:width height:height duration:duration];
110 | }
111 |
112 | + (CFAAction *)resizeToWidth:(CGFloat)width height:(CGFloat)height duration:(NSTimeInterval)duration {
113 | return [CFAResize resizeToWidth:width height:height duration:duration];
114 | }
115 |
116 | + (CFAAction *)resizeToWidth:(CGFloat)width duration:(NSTimeInterval)duration {
117 | return [CFAResize resizeToWidth:width duration:duration];
118 | }
119 |
120 | + (CFAAction *)resizeToHeight:(CGFloat)height duration:(NSTimeInterval)duration {
121 | return [CFAResize resizeToHeight:height duration:duration];
122 | }
123 |
124 | + (CFAAction *)scaleBy:(CGFloat)scale duration:(NSTimeInterval)sec {
125 | return [CFAScale scaleBy:scale duration:sec];
126 | }
127 |
128 | + (CFAAction *)scaleXBy:(CGFloat)xScale y:(CGFloat)yScale duration:(NSTimeInterval)sec {
129 | return [CFAScale scaleXBy:xScale y:yScale duration:sec];
130 | }
131 |
132 | + (CFAAction *)scaleTo:(CGFloat)scale duration:(NSTimeInterval)sec {
133 | return [CFAScale scaleTo:scale duration:sec];
134 | }
135 |
136 | + (CFAAction *)scaleXTo:(CGFloat)xScale y:(CGFloat)yScale duration:(NSTimeInterval)sec {
137 | return [CFAScale scaleXTo:xScale y:yScale duration:sec];
138 | }
139 |
140 | + (CFAAction *)scaleXTo:(CGFloat)scale duration:(NSTimeInterval)sec {
141 | return [CFAScale scaleXTo:scale duration:sec];
142 | }
143 |
144 | + (CFAAction *)scaleYTo:(CGFloat)scale duration:(NSTimeInterval)sec {
145 | return [CFAScale scaleYTo:scale duration:sec];
146 | }
147 |
148 | + (CFAAction *)hide {
149 | return [CFAHide hide];
150 | }
151 |
152 | + (CFAAction *)unhide {
153 | return [CFAHide unhide];
154 | }
155 |
156 | + (CFAAction *)sequence:(NSArray *)actions {
157 | return [CFASequence sequenceWithActions:actions];
158 | }
159 |
160 | + (CFAAction *)group:(NSArray *)actions {
161 | return [CFAGroup groupWithActions:actions];
162 | }
163 |
164 | + (CFAAction *)repeatAction:(CFAAction *)action count:(NSUInteger)count {
165 | return [CFARepeat repeatAction:action count:count];
166 | }
167 |
168 | + (CFAAction *)repeatActionForever:(CFAAction *)action {
169 | return [CFARepeat repeatActionForever:action];
170 | }
171 |
172 | + (CFAAction *)fadeInWithDuration:(NSTimeInterval)sec {
173 | return [CFAFade fadeInWithDuration:sec];
174 | }
175 |
176 | + (CFAAction *)fadeOutWithDuration:(NSTimeInterval)sec {
177 | return [CFAFade fadeOutWithDuration:sec];
178 | }
179 |
180 | + (CFAAction *)fadeAlphaBy:(CGFloat)factor duration:(NSTimeInterval)sec {
181 | return [CFAFade fadeAlphaBy:factor duration:sec];
182 | }
183 |
184 | + (CFAAction *)fadeAlphaTo:(CGFloat)alpha duration:(NSTimeInterval)sec {
185 | return [CFAFade fadeAlphaTo:alpha duration:sec];
186 | }
187 |
188 | + (CFAAction *)followPath:(CGPathRef)path duration:(NSTimeInterval)sec {
189 | return [CFAFollowPath followPath:path duration:sec];
190 | }
191 |
192 | + (CFAAction *)followPath:(CGPathRef)path asOffset:(BOOL)offset orientToPath:(BOOL)orient duration:(NSTimeInterval)sec {
193 | return [CFAFollowPath followPath:path asOffset:offset orientToPath:orient duration:sec];
194 | }
195 |
196 | + (CFAAction *)speedBy:(CGFloat)speed duration:(NSTimeInterval)sec {
197 | return [CFASpeed speedBy:speed duration:sec];
198 | }
199 |
200 | + (CFAAction *)speedTo:(CGFloat)speed duration:(NSTimeInterval)sec {
201 | return [CFASpeed speedTo:speed duration:sec];
202 | }
203 |
204 | + (CFAAction *)waitForDuration:(NSTimeInterval)sec {
205 | return [CFAWait waitForDuration:sec];
206 | }
207 |
208 | + (CFAAction *)waitForDuration:(NSTimeInterval)sec withRange:(NSTimeInterval)durationRange {
209 | return [CFAWait waitForDuration:sec withRange:durationRange];
210 | }
211 |
212 | + (CFAAction *)performSelector:(SEL)selector onTarget:(id)target {
213 | return [CFAPerformSelector performSelector:selector onTarget:target];
214 | }
215 |
216 | + (CFAAction *)runBlock:(dispatch_block_t)block {
217 | return [CFARunBlock runBlock:block queue:dispatch_get_main_queue()];
218 | }
219 |
220 | + (CFAAction *)runBlock:(dispatch_block_t)block queue:(dispatch_queue_t)queue {
221 | return [CFARunBlock runBlock:block queue:queue];
222 | }
223 |
224 | + (CFAAction *)customActionWithDuration:(NSTimeInterval)seconds actionBlock:(void (^)(CALayer *node, CGFloat elapsedTime))block {
225 | return [CFACustomAction customActionWithDuration:seconds actionBlock:block];
226 | }
227 |
228 | @end
229 |
230 | @implementation CALayer (CFAAction)
231 |
232 | - (void)cfa_runAction:(CFAAction *)action {
233 | [action executeWithTarget:self forTime:CACurrentMediaTime()];
234 | }
235 |
236 | - (void)cfa_runAction:(CFAAction *)action completion:(void (^)(void))block {
237 | [action setOnCompletion:block];
238 | [action executeWithTarget:self forTime:CACurrentMediaTime()];
239 | }
240 |
241 | @end
--------------------------------------------------------------------------------
/CFAAction/CFACustomAction.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFACustomAction.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFACustomAction : CFAAction
15 |
16 | + (CFAAction *)customActionWithDuration:(NSTimeInterval)seconds actionBlock:(void (^)(CALayer *node, CGFloat elapsedTime))block;
17 |
18 | @end
19 |
20 | NS_ASSUME_NONNULL_END
21 |
--------------------------------------------------------------------------------
/CFAAction/CFACustomAction.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFACustomAction.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFACustomAction.h"
11 |
12 | @implementation CFACustomAction {
13 | void (^_actionBlock)(CALayer *node, CGFloat elapsedTime);
14 | }
15 |
16 | + (CFAAction *)customActionWithDuration:(NSTimeInterval)seconds actionBlock:(void (^)(CALayer *node, CGFloat elapsedTime))block {
17 | CFACustomAction *action = [[CFACustomAction alloc] init];
18 |
19 | action->_actionBlock = [block copy];
20 | action.duration = seconds;
21 |
22 | return action;
23 | }
24 |
25 | - (id)copyWithZone:(NSZone *)zone {
26 | CFACustomAction *copyAction = [super copyWithZone:zone];
27 | copyAction->_actionBlock = [_actionBlock copy];
28 |
29 | return copyAction;
30 | }
31 |
32 | - (CFAAction *)reversedAction {
33 | return [self copy];
34 | }
35 |
36 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
37 | NSCAssert(_actionBlock != NULL, @"CFACustomAction created with NULL custom action");
38 |
39 | _actionBlock(target, time);
40 | self.finished = YES;
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/CFAAction/CFAFade.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFAFade.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFAFade : CFAAction
15 |
16 | + (CFAAction *)fadeInWithDuration:(NSTimeInterval)sec;
17 | + (CFAAction *)fadeOutWithDuration:(NSTimeInterval)sec;
18 | + (CFAAction *)fadeAlphaBy:(CGFloat)factor duration:(NSTimeInterval)sec;
19 | + (CFAAction *)fadeAlphaTo:(CGFloat)alpha duration:(NSTimeInterval)sec;
20 |
21 | @end
22 |
23 | NS_ASSUME_NONNULL_END
24 |
--------------------------------------------------------------------------------
/CFAAction/CFAFade.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFAFade.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAFade.h"
11 |
12 | static NSString *const CFAFadeKeypath = @"opacity";
13 |
14 | typedef NS_ENUM(int, CFFadeSubtype) {
15 | CFFadeSubtypeNone = 0,
16 | CFFadeSubtypeDelta,
17 | CFFadeSubtypeDirect,
18 | CFFadeSubtypeIn,
19 | CFFadeSubtypeOut
20 | };
21 |
22 | @implementation CFAFade {
23 | CGFloat _opacity;
24 | CFFadeSubtype _subtype;
25 | }
26 |
27 | + (CFAAction *)fadeInWithDuration:(NSTimeInterval)sec {
28 | CFAFade *fade = (CFAFade *)[CFAFade fadeAlphaTo:1.0f duration:sec];
29 | fade->_subtype = CFFadeSubtypeIn;
30 | return fade;
31 | }
32 |
33 | + (CFAAction *)fadeOutWithDuration:(NSTimeInterval)sec {
34 | CFAFade *fade = (CFAFade *)[CFAFade fadeAlphaTo:0.0f duration:sec];
35 | fade->_subtype = CFFadeSubtypeOut;
36 | return fade;
37 | }
38 |
39 | + (CFAAction *)fadeAlphaBy:(CGFloat)factor duration:(NSTimeInterval)sec {
40 | CFAFade *fadeAnimation = [[CFAFade alloc] init];
41 |
42 | fadeAnimation->_opacity = factor;
43 | fadeAnimation->_subtype = CFFadeSubtypeDelta;
44 | fadeAnimation.duration = sec;
45 |
46 | return fadeAnimation;
47 | }
48 |
49 | + (CFAAction *)fadeAlphaTo:(CGFloat)alpha duration:(NSTimeInterval)sec {
50 | CFAFade *fadeAnimation = [[CFAFade alloc] init];
51 |
52 | fadeAnimation->_opacity = alpha;
53 | fadeAnimation->_subtype = CFFadeSubtypeDirect;
54 | fadeAnimation.duration = sec;
55 |
56 | return fadeAnimation;
57 | }
58 |
59 | - (id)copyWithZone:(NSZone *)zone {
60 | CFAFade *copiedAction = [super copyWithZone:NULL];
61 | copiedAction->_opacity = _opacity;
62 | copiedAction->_subtype = _subtype;
63 | copiedAction.duration = self.duration;
64 | return copiedAction;
65 | }
66 |
67 | - (CFAAction *)reversedAction {
68 | if (_subtype == CFFadeSubtypeDirect) {
69 | return [self copy];
70 | } else if (_subtype == CFFadeSubtypeIn) {
71 | return [CFAFade fadeOutWithDuration:self.duration];
72 | } else if (_subtype == CFFadeSubtypeOut) {
73 | return [CFAFade fadeInWithDuration:self.duration];
74 | }
75 | CFAFade *copiedAction = [super copyWithZone:NULL];
76 | copiedAction->_opacity = -_opacity;
77 | copiedAction->_subtype = _subtype;
78 | copiedAction.duration = self.duration;
79 | return copiedAction;
80 | }
81 |
82 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
83 | CGFloat newOpacity = [target.presentationLayer opacity];
84 | switch (_subtype) {
85 | case CFFadeSubtypeDelta:
86 | newOpacity += _opacity;
87 | break;
88 | case CFFadeSubtypeOut:
89 | case CFFadeSubtypeIn:
90 | case CFFadeSubtypeDirect:
91 | newOpacity = _opacity;
92 | break;
93 | default:
94 | break;
95 | }
96 |
97 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:CFAFadeKeypath];
98 | animation.removedOnCompletion = NO;
99 | animation.fillMode = kCAFillModeForwards;
100 | animation.beginTime = time;
101 | animation.fromValue = [target.presentationLayer ?: target valueForKeyPath:CFAFadeKeypath];
102 | animation.toValue = @(newOpacity);
103 | animation.duration = self.duration;
104 | animation.timingFunction = self.timingFunction;
105 | [animation setDelegate:self];
106 | [target.presentationLayer ?: target addAnimation:animation forKey:CFAFadeKeypath];
107 | }
108 |
109 | - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
110 | self.finished = YES;
111 | }
112 |
113 | @end
114 |
--------------------------------------------------------------------------------
/CFAAction/CFAFollowPath.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFAFollowPath.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFAFollowPath : CFAAction
15 |
16 | + (CFAAction *)followPath:(CGPathRef)path duration:(NSTimeInterval)sec;
17 | + (CFAAction *)followPath:(CGPathRef)path asOffset:(BOOL)offset orientToPath:(BOOL)orient duration:(NSTimeInterval)sec;
18 |
19 | @end
20 |
21 | NS_ASSUME_NONNULL_END
22 |
--------------------------------------------------------------------------------
/CFAAction/CFAFollowPath.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFAFollowPath.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAFollowPath.h"
11 | #ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
12 | #import "NSBezierPath+CFABezierPathQuartzAssistant.h"
13 | #else
14 | #import
15 | #endif
16 |
17 | static NSString *const CFAFollowPathKeypath = @"position";
18 |
19 | @implementation CFAFollowPath {
20 | CGPathRef _cgPath;
21 | }
22 |
23 | + (CFAAction *)followPath:(CGPathRef)path duration:(NSTimeInterval)sec {
24 | CFAFollowPath *pathFollowAction = [[CFAFollowPath alloc] init];
25 |
26 | pathFollowAction->_cgPath = CGPathRetain(path);
27 | pathFollowAction.duration = sec;
28 |
29 | return pathFollowAction;
30 | }
31 |
32 | + (CFAAction *)followPath:(CGPathRef)path asOffset:(BOOL)offset orientToPath:(BOOL)orient duration:(NSTimeInterval)sec {
33 | CFAFollowPath *pathFollowAction = [[CFAFollowPath alloc] init];
34 |
35 | pathFollowAction->_cgPath = CGPathRetain(path);
36 | pathFollowAction.duration = sec;
37 |
38 | return pathFollowAction;
39 | }
40 |
41 | - (id)copyWithZone:(NSZone *)zone {
42 | CFAFollowPath *copiedAction = [super copyWithZone:NULL];
43 | copiedAction->_cgPath = CGPathRetain(_cgPath);
44 | copiedAction.duration = self.duration;
45 | return copiedAction;
46 | }
47 |
48 | - (CFAAction *)reversedAction {
49 | CFAFollowPath *reversedAction = [super copyWithZone:NULL];
50 | #ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
51 | NSBezierPath *path = [NSBezierPath bezierPath];
52 | CGPathApply(_cgPath, (__bridge void *)path, CFAPathToBezierApplier);
53 | reversedAction->_cgPath = path.bezierPathByReversingPath.quartzPath;
54 | #else
55 | UIBezierPath *path = [UIBezierPath bezierPathWithCGPath:_cgPath];
56 | reversedAction->_cgPath = CGPathRetain(path.bezierPathByReversingPath.CGPath);
57 | #endif
58 | reversedAction.duration = self.duration;
59 | return reversedAction;
60 | }
61 |
62 | - (void)dealloc {
63 | if (_cgPath) {
64 | CGPathRelease(_cgPath);
65 | }
66 | }
67 |
68 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
69 | CAKeyframeAnimation * pathAnimation = [CAKeyframeAnimation animationWithKeyPath:CFAFollowPathKeypath];
70 | pathAnimation.path = _cgPath;
71 | pathAnimation.duration = self.duration;
72 | pathAnimation.calculationMode = kCAAnimationPaced;
73 | pathAnimation.beginTime = time;
74 | pathAnimation.removedOnCompletion = NO;
75 | pathAnimation.fillMode = kCAFillModeForwards;
76 | pathAnimation.timingFunction = self.timingFunction;
77 | [pathAnimation setDelegate:self];
78 | [target addAnimation:pathAnimation forKey:CFAFollowPathKeypath];
79 | }
80 |
81 | - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
82 | self.finished = YES;
83 | }
84 |
85 | #ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
86 | static void CFAPathToBezierApplier(void *info, const CGPathElement *element) {
87 | NSBezierPath *path = (__bridge NSBezierPath *)info;
88 | switch (element->type) {
89 | case kCGPathElementMoveToPoint:
90 | [path moveToPoint:element->points[0]];
91 | break;
92 |
93 | case kCGPathElementAddLineToPoint:
94 | [path lineToPoint:element->points[0]];
95 | break;
96 |
97 | case kCGPathElementAddQuadCurveToPoint:
98 | [path curveToPoint:element->points[1] controlPoint1:element->points[0] controlPoint2:element->points[0]];
99 | break;
100 |
101 | case kCGPathElementAddCurveToPoint:
102 | [path curveToPoint:element->points[2] controlPoint1:element->points[0] controlPoint2:element->points[1]];
103 | break;
104 |
105 | case kCGPathElementCloseSubpath:
106 | [path closePath];
107 | break;
108 | }
109 | }
110 | #endif
111 |
112 | @end
113 |
--------------------------------------------------------------------------------
/CFAAction/CFAGroup.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFAGroup.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFAGroup : CFAAction
15 |
16 | + (instancetype)groupWithActions:(NSArray *)actions;
17 |
18 | @end
19 |
20 | NS_ASSUME_NONNULL_END
21 |
--------------------------------------------------------------------------------
/CFAAction/CFAGroup.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFAGroup.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAGroup.h"
11 | #import "CFASequence.h"
12 |
13 | @implementation CFAGroup {
14 | NSArray *_actions;
15 | }
16 |
17 | - (id)init {
18 | self = [super init];
19 |
20 | _actions = [[NSArray alloc] init];
21 |
22 | return self;
23 | }
24 |
25 | + (instancetype)groupWithActions:(NSArray *)actions {
26 | CFAGroup *sequence = nil;
27 | if (actions != nil) {
28 | if (actions.count != 0) {
29 | NSMutableArray *groupedActions = [[NSMutableArray alloc] initWithCapacity:actions.count];
30 | for (id action in actions) {
31 | if (![action isKindOfClass:NSArray.class]) {
32 | [groupedActions addObject:[action copy]];
33 | } else {
34 | [groupedActions addObject:[CFASequence sequenceWithActions:action]];
35 | }
36 | }
37 | sequence = [[CFAGroup alloc] init];
38 | sequence->_actions = groupedActions.copy;
39 | NSTimeInterval accumulator = 0.f;
40 | for (CFAAction *group in groupedActions) {
41 | accumulator = MAX(accumulator, group.duration);
42 | }
43 | [sequence setDuration:accumulator];
44 | }
45 | }
46 | return sequence;
47 | }
48 |
49 | - (id)copyWithZone:(NSZone *)zone {
50 | return [CFAGroup groupWithActions:_actions];
51 | }
52 |
53 | - (CFAAction *)reversedAction {
54 | NSMutableArray *reversedActions = [NSMutableArray arrayWithCapacity:_actions.count];
55 | for (CFAAction *action in _actions) {
56 | [reversedActions addObject:[action reversedAction]];
57 | }
58 | return [CFAGroup groupWithActions:reversedActions];
59 | }
60 |
61 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
62 | for (CFAAction *action in _actions) {
63 | [action executeWithTarget:target forTime:time];
64 | }
65 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.duration * NSEC_PER_SEC));
66 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
67 | self.finished = YES;
68 | });
69 | }
70 |
71 | - (BOOL)finished {
72 | BOOL finished = YES;
73 | for (CFAAction *action in _actions) {
74 | if (!action.finished) return NO;
75 | }
76 | return finished;
77 | }
78 |
79 | @end
80 |
--------------------------------------------------------------------------------
/CFAAction/CFAHide.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFAHide.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 12/9/14.
6 | // Copyright (c) 2014 CodaFi. All rights reserved.
7 | //
8 |
9 | #import "CFAAction+Private.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface CFAHide : CFAAction
14 |
15 | @end
16 |
17 | NS_ASSUME_NONNULL_END
18 |
--------------------------------------------------------------------------------
/CFAAction/CFAHide.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFAHide.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 12/9/14.
6 | // Copyright (c) 2014 CodaFi. All rights reserved.
7 | //
8 |
9 | #import "CFAHide.h"
10 |
11 | @implementation CFAHide {
12 | BOOL _willHideNode;
13 | }
14 |
15 | + (CFAAction *)hide {
16 | CFAHide *hideAction = [[CFAHide alloc] init];
17 | hideAction->_willHideNode = YES;
18 | return hideAction;
19 | }
20 |
21 | + (CFAAction *)unhide {
22 | CFAHide *hideAction = [[CFAHide alloc] init];
23 | hideAction->_willHideNode = NO;
24 | return hideAction;
25 | }
26 |
27 | - (id)copyWithZone:(NSZone *)zone {
28 | CFAHide *copiedAction = [super copyWithZone:zone];
29 | copiedAction->_willHideNode = _willHideNode;
30 | return copiedAction;
31 | }
32 |
33 | - (CFAAction *)reversedAction {
34 | CFAHide *copiedAction = [super copyWithZone:NULL];
35 | copiedAction->_willHideNode = !_willHideNode;
36 | return copiedAction;
37 | }
38 |
39 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
40 | target.hidden = _willHideNode;
41 | self.finished = YES;
42 | }
43 |
44 | @end
45 |
--------------------------------------------------------------------------------
/CFAAction/CFAMove.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFAMove.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFAMove : CFAAction
15 |
16 | + (CFAAction *)moveByX:(CGFloat)deltaX y:(CGFloat)deltaY duration:(NSTimeInterval)sec;
17 | #if CGVECTOR_DEFINED
18 | + (CFAAction *)moveBy:(CGVector)delta duration:(NSTimeInterval)sec;
19 | #endif
20 | + (CFAAction *)moveTo:(CGPoint)location duration:(NSTimeInterval)sec;
21 | + (CFAAction *)moveToX:(CGFloat)x duration:(NSTimeInterval)sec;
22 | + (CFAAction *)moveToY:(CGFloat)y duration:(NSTimeInterval)sec;
23 |
24 | @end
25 |
26 | NS_ASSUME_NONNULL_END
27 |
--------------------------------------------------------------------------------
/CFAAction/CFAMove.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFAMove.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAMove.h"
11 | #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
12 | #import
13 | #endif
14 |
15 | static NSString *const CFAMoveKeypath = @"position";
16 |
17 | typedef NS_ENUM(int, CFMoveSubtype) {
18 | CFMoveSubtypeNone = 0,
19 | CFMoveSubtypeDelta,
20 | CFMoveSubtypeDirect
21 | };
22 |
23 | @implementation CFAMove {
24 | double x, y;
25 | CFMoveSubtype _subtype;
26 | }
27 |
28 | #if CGVECTOR_DEFINED
29 | + (CFAAction *)moveBy:(CGVector)delta duration:(NSTimeInterval)sec {
30 | return [CFAMove moveByX:delta.dx y:delta.dy duration:sec];
31 | }
32 | #endif
33 |
34 | + (CFAAction *)moveByX:(CGFloat)deltaX y:(CGFloat)deltaY duration:(NSTimeInterval)sec {
35 | CFAMove *moveAction = [[CFAMove alloc] init];
36 |
37 | moveAction->x = deltaX;
38 | moveAction->y = deltaY;
39 | moveAction->_subtype = CFMoveSubtypeDelta;
40 | moveAction.duration = sec;
41 |
42 | return moveAction;
43 | }
44 |
45 | + (CFAAction *)moveTo:(CGPoint)location duration:(NSTimeInterval)sec {
46 | return [CFAMove moveToX:location.x y:location.y duration:sec];
47 | }
48 |
49 | + (CFAAction *)moveToX:(CGFloat)x duration:(NSTimeInterval)sec {
50 | return [CFAMove moveToX:x y:0.0f duration:sec];
51 | }
52 |
53 | + (CFAAction *)moveToY:(CGFloat)y duration:(NSTimeInterval)sec {
54 | return [CFAMove moveToX:0.0f y:y duration:sec];
55 | }
56 |
57 | + (CFAAction *)moveToX:(CGFloat)x y:(CGFloat)y duration:(NSTimeInterval)sec {
58 | CFAMove *moveAction = [[CFAMove alloc] init];
59 |
60 | moveAction->x = x;
61 | moveAction->y = y;
62 | moveAction.duration = sec;
63 | moveAction->_subtype = CFMoveSubtypeDirect;
64 |
65 | return moveAction;
66 | }
67 |
68 | - (id)copyWithZone:(NSZone *)zone {
69 | CFAMove *copiedAction = [super copyWithZone:zone];
70 | copiedAction->x = x;
71 | copiedAction->y = y;
72 | copiedAction->_subtype = _subtype;
73 | copiedAction.duration = self.duration;
74 | return copiedAction;
75 | }
76 |
77 | - (CFAAction *)reversedAction {
78 | if (_subtype == CFMoveSubtypeDirect) {
79 | return [self copy];
80 | }
81 | CFAMove *copiedAction = [super copyWithZone:NULL];
82 | copiedAction->x = -x;
83 | copiedAction->y = -y;
84 | copiedAction->_subtype = _subtype;
85 | copiedAction.duration = self.duration;
86 | return copiedAction;
87 | }
88 |
89 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
90 | CGPoint newPosition = [(CALayer *)target.presentationLayer ?: target position];
91 | switch (_subtype) {
92 | case CFMoveSubtypeDelta:
93 | newPosition.x += x;
94 | newPosition.y += y;
95 | break;
96 | case CFMoveSubtypeDirect:
97 | newPosition.x = x;
98 | newPosition.y = y;
99 | break;
100 | default:
101 | break;
102 | }
103 |
104 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:CFAMoveKeypath];
105 | animation.removedOnCompletion = NO;
106 | animation.fillMode = kCAFillModeForwards;
107 | animation.beginTime = time;
108 | animation.fromValue = [(CALayer *)target.presentationLayer ?: target valueForKey:CFAMoveKeypath];
109 | #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
110 | animation.toValue = [NSValue valueWithCGPoint:newPosition];
111 | #else
112 | animation.toValue = [NSValue valueWithPoint:newPosition];
113 | #endif
114 | animation.duration = self.duration;
115 | animation.repeatCount = self.repeatCount;
116 | animation.cumulative = YES;
117 | animation.timingFunction = self.timingFunction;
118 | [animation setDelegate:self];
119 | [target.presentationLayer ?: target addAnimation:animation forKey:CFAMoveKeypath];
120 | }
121 |
122 | - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
123 | self.finished = YES;
124 | }
125 |
126 | @end
127 |
--------------------------------------------------------------------------------
/CFAAction/CFAPerformSelector.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFAPerformSelector.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFAPerformSelector : CFAAction
15 |
16 | + (CFAAction *)performSelector:(SEL)selector onTarget:(id)target;
17 |
18 | @end
19 |
20 | NS_ASSUME_NONNULL_END
21 |
--------------------------------------------------------------------------------
/CFAAction/CFAPerformSelector.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFAPerformSelector.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAPerformSelector.h"
11 | #include
12 |
13 | @implementation CFAPerformSelector {
14 | SEL _selector;
15 | id _target;
16 | }
17 |
18 | + (CFAAction *)performSelector:(SEL)selector onTarget:(id)target {
19 | CFAPerformSelector *action = [[CFAPerformSelector alloc] init];
20 |
21 | action->_selector = selector;
22 | action->_target = target;
23 |
24 | return action;
25 | }
26 |
27 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
28 | if (!self.finished) {
29 | if ((_target != nil) && (_selector != NULL)) {
30 | void(*cfa_msgSend)(id self, SEL _cmd) = (void *)objc_msgSend;
31 | cfa_msgSend(_target, _selector);
32 | }
33 | self.finished = YES;
34 | }
35 | }
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/CFAAction/CFARepeat.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFARepeat.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFARepeat : CFAAction
15 |
16 | + (CFAAction *)repeatAction:(CFAAction *)action count:(NSUInteger)count;
17 | + (CFAAction *)repeatActionForever:(CFAAction *)action;
18 |
19 | @end
20 |
21 | NS_ASSUME_NONNULL_END
22 |
--------------------------------------------------------------------------------
/CFAAction/CFARepeat.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFARepeat.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFARepeat.h"
11 |
12 | @implementation CFARepeat {
13 | CFAAction *_repeatedAction;
14 | float _count;
15 | BOOL _forever;
16 | }
17 |
18 | + (CFAAction *)repeatAction:(CFAAction *)action count:(NSUInteger)count {
19 | NSParameterAssert(action != nil);
20 |
21 | CFARepeat *repeatAction = [[CFARepeat alloc] init];
22 |
23 | repeatAction->_repeatedAction = [action copy];
24 | repeatAction->_count = count;
25 | repeatAction->_forever = NO;
26 | repeatAction.duration = action.duration * ((count < 1) ? 1 : count);
27 |
28 | return repeatAction;
29 | }
30 |
31 | + (CFAAction *)repeatActionForever:(CFAAction *)action {
32 | NSParameterAssert(action != nil);
33 |
34 | CFARepeat *repeatAction = [[CFARepeat alloc] init];
35 |
36 | repeatAction->_repeatedAction = [action copy];
37 | repeatAction->_count = HUGE_VALF;
38 | repeatAction.duration = action.duration * HUGE_VALF;
39 |
40 | return repeatAction;
41 | }
42 |
43 | - (id)copyWithZone:(NSZone *)zone {
44 | CFARepeat *repeatedCopy = nil;
45 |
46 | if (_forever) {
47 | repeatedCopy = (CFARepeat *)[CFARepeat repeatActionForever:_repeatedAction];
48 | } else {
49 | repeatedCopy = (CFARepeat *)[CFARepeat repeatAction:_repeatedAction count:_count];
50 | }
51 |
52 | return repeatedCopy;
53 | }
54 |
55 | - (CFAAction *)reversedAction {
56 | return [self copy];
57 | }
58 |
59 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
60 | _repeatedAction.repeatCount = _count;
61 | [_repeatedAction executeWithTarget:target forTime:time];
62 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.duration * NSEC_PER_SEC));
63 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
64 | self.finished = YES;
65 | });
66 | }
67 |
68 |
69 | @end
70 |
--------------------------------------------------------------------------------
/CFAAction/CFAResize.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFAResize.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFAResize : CFAAction
15 |
16 | + (CFAAction *)resizeByWidth:(CGFloat)width height:(CGFloat)height duration:(NSTimeInterval)duration;
17 | + (CFAAction *)resizeToWidth:(CGFloat)width height:(CGFloat)height duration:(NSTimeInterval)duration;
18 | + (CFAAction *)resizeToWidth:(CGFloat)width duration:(NSTimeInterval)duration;
19 | + (CFAAction *)resizeToHeight:(CGFloat)height duration:(NSTimeInterval)duration;
20 |
21 | @end
22 |
23 | NS_ASSUME_NONNULL_END
24 |
--------------------------------------------------------------------------------
/CFAAction/CFAResize.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFAResize.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAResize.h"
11 | #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
12 | #import
13 | #endif
14 |
15 | static NSString *const CFAResizeKeypath = @"bounds";
16 |
17 | typedef NS_ENUM(int, CFResizeSubtype) {
18 | CFResizeSubtypeNone = 0,
19 | CFResizeSubtypeDelta,
20 | CFResizeSubtypeDirect
21 | };
22 |
23 | @implementation CFAResize {
24 | double width, height;
25 | CFResizeSubtype _subtype;
26 | }
27 |
28 | + (CFAAction *)resizeByWidth:(CGFloat)width height:(CGFloat)height duration:(NSTimeInterval)duration {
29 | CFAResize *resizeAction = [[CFAResize alloc] init];
30 |
31 | resizeAction->width = width;
32 | resizeAction->height = height;
33 | resizeAction.duration = duration;
34 | resizeAction->_subtype = CFResizeSubtypeDelta;
35 |
36 | return resizeAction;
37 | }
38 |
39 | + (CFAAction *)resizeToWidth:(CGFloat)width height:(CGFloat)height duration:(NSTimeInterval)duration {
40 | CFAResize *resizeAction = [[CFAResize alloc] init];
41 |
42 | resizeAction->width = width;
43 | resizeAction->height = height;
44 | resizeAction.duration = duration;
45 | resizeAction->_subtype = CFResizeSubtypeDirect;
46 |
47 | return resizeAction;
48 | }
49 |
50 | + (CFAAction *)resizeToWidth:(CGFloat)width duration:(NSTimeInterval)duration {
51 | return [CFAResize resizeToWidth:width height:MAXFLOAT duration:duration];
52 | }
53 |
54 | + (CFAAction *)resizeToHeight:(CGFloat)height duration:(NSTimeInterval)duration {
55 | return [CFAResize resizeToWidth:MAXFLOAT height:height duration:duration];
56 | }
57 |
58 | - (id)copyWithZone:(NSZone *)zone {
59 | CFAResize *copiedAction = [super copyWithZone:zone];
60 | copiedAction->width = width;
61 | copiedAction->height = height;
62 | copiedAction->_subtype = _subtype;
63 | copiedAction.duration = self.duration;
64 | return copiedAction;
65 | }
66 |
67 | - (CFAAction *)reversedAction {
68 | if (_subtype == CFResizeSubtypeDirect) {
69 | return [self copy];
70 | }
71 | CFAResize *copiedAction = [super copyWithZone:NULL];
72 | copiedAction->width = -width;
73 | copiedAction->height = -height;
74 | copiedAction->_subtype = _subtype;
75 | return copiedAction;
76 | }
77 |
78 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
79 | CGRect newFrame = [target.presentationLayer ?:target bounds];
80 | switch (_subtype) {
81 | case CFResizeSubtypeDelta:
82 | if (width != MAXFLOAT)
83 | newFrame.size.width += width;
84 | if (height != MAXFLOAT)
85 | newFrame.size.height += height;
86 | break;
87 | case CFResizeSubtypeDirect:
88 | if (width != MAXFLOAT)
89 | newFrame.size.width = width;
90 | if (height != MAXFLOAT)
91 | newFrame.size.height = height;
92 | break;
93 | default:
94 | break;
95 | }
96 |
97 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:CFAResizeKeypath];
98 | animation.fillMode = kCAFillModeForwards;
99 | animation.beginTime = time;
100 | animation.removedOnCompletion = NO;
101 | #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
102 | animation.fromValue = [NSValue valueWithCGRect:[target.presentationLayer ?:target bounds]];
103 | animation.toValue = [NSValue valueWithCGRect:newFrame];
104 | #else
105 | animation.fromValue = [NSValue valueWithRect:[target.presentationLayer ?:target bounds]];
106 | animation.toValue = [NSValue valueWithRect:newFrame];
107 | #endif
108 | animation.duration = self.duration;
109 | animation.repeatCount = self.repeatCount;
110 | animation.cumulative = YES;
111 | animation.timingFunction = self.timingFunction;
112 | [target.presentationLayer ?:target addAnimation:animation forKey:CFAResizeKeypath];
113 | }
114 |
115 | - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
116 | self.finished = YES;
117 | }
118 |
119 | @end
120 |
121 |
--------------------------------------------------------------------------------
/CFAAction/CFARotate.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFARotate.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFARotate : CFAAction
15 |
16 | + (CFAAction *)rotateByAngle:(CGFloat)radians duration:(NSTimeInterval)sec;
17 | + (CFAAction *)rotateToAngle:(CGFloat)radians duration:(NSTimeInterval)sec;
18 | + (CFAAction *)rotateToAngle:(CGFloat)radians duration:(NSTimeInterval)sec shortestUnitArc:(BOOL)shortestUnitArc;
19 |
20 | @end
21 |
22 | NS_ASSUME_NONNULL_END
23 |
--------------------------------------------------------------------------------
/CFAAction/CFARotate.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFARotate.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFARotate.h"
11 |
12 | static NSString *const CFARotateKeypath = @"transform.rotation";
13 |
14 | typedef NS_ENUM(int, CFRotateSubtype) {
15 | CFRotateSubtypeNone = 0,
16 | CFRotateSubtypeDelta,
17 | CFRotateSubtypeDirect
18 | };
19 |
20 | @implementation CFARotate {
21 | CGFloat _angle;
22 | CFRotateSubtype _subtype;
23 | }
24 |
25 | + (CFAAction *)rotateByAngle:(CGFloat)radians duration:(NSTimeInterval)sec {
26 | CFARotate *resizeAction = [[CFARotate alloc] init];
27 |
28 | resizeAction->_angle = radians;
29 | resizeAction.duration = sec;
30 | resizeAction->_subtype = CFRotateSubtypeDelta;
31 |
32 | return resizeAction;
33 | }
34 |
35 | + (CFAAction *)rotateToAngle:(CGFloat)radians duration:(NSTimeInterval)sec {
36 | return [CFARotate rotateToAngle:radians duration:sec shortestUnitArc:NO];
37 | }
38 |
39 | + (CFAAction *)rotateToAngle:(CGFloat)radians duration:(NSTimeInterval)sec shortestUnitArc:(BOOL)shortestUnitArc {
40 | CFARotate *resizeAction = [[CFARotate alloc] init];
41 |
42 | resizeAction->_angle = radians;
43 | resizeAction.duration = sec;
44 | resizeAction->_subtype = CFRotateSubtypeDirect;
45 |
46 | return resizeAction;
47 | }
48 |
49 | - (id)copyWithZone:(NSZone *)zone {
50 | CFARotate *copiedAction = [super copyWithZone:zone];
51 | copiedAction->_angle = _angle;
52 | copiedAction->_subtype = _subtype;
53 | copiedAction.duration = self.duration;
54 | return copiedAction;
55 | }
56 |
57 | - (CFAAction *)reversedAction {
58 | if (_subtype == CFRotateSubtypeDirect) {
59 | return [self copy];
60 | }
61 | CFARotate *copiedAction = [super copyWithZone:NULL];
62 | copiedAction->_angle = -_angle;
63 | copiedAction->_subtype = _subtype;
64 | copiedAction.duration = self.duration;
65 | return copiedAction;
66 | }
67 |
68 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
69 | CGFloat angle = [(NSNumber *)[target.presentationLayer valueForKeyPath:@"transform.rotation"] floatValue];
70 | switch (_subtype) {
71 | case CFRotateSubtypeDelta:
72 | angle += _angle;
73 | break;
74 | case CFRotateSubtypeDirect:
75 | angle = _angle;
76 | break;
77 | default:
78 | break;
79 | }
80 |
81 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:CFARotateKeypath];
82 | animation.removedOnCompletion = NO;
83 | animation.fillMode = kCAFillModeForwards;
84 | animation.beginTime = time;
85 | animation.fromValue = [target.presentationLayer valueForKeyPath:@"transform.rotation"];
86 | animation.toValue = @(_angle);
87 | animation.duration = self.duration;
88 | animation.repeatCount = self.repeatCount;
89 | animation.cumulative = YES;
90 | animation.timingFunction = self.timingFunction;
91 | [animation setDelegate:self];
92 | [target.presentationLayer ?: target addAnimation:animation forKey:CFARotateKeypath];
93 | }
94 |
95 | - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
96 | self.finished = YES;
97 | }
98 |
99 |
100 | @end
101 |
--------------------------------------------------------------------------------
/CFAAction/CFARunBlock.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFARunBlock.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFARunBlock : CFAAction
15 |
16 | + (CFAAction *)runBlock:(dispatch_block_t)block;
17 | + (CFAAction *)runBlock:(dispatch_block_t)block queue:(dispatch_queue_t)queue;
18 |
19 | @end
20 |
21 | NS_ASSUME_NONNULL_END
22 |
--------------------------------------------------------------------------------
/CFAAction/CFARunBlock.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFARunBlock.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFARunBlock.h"
11 |
12 | @implementation CFARunBlock {
13 | dispatch_block_t _block;
14 | dispatch_queue_t _queue;
15 | }
16 |
17 | + (CFAAction *)runBlock:(dispatch_block_t)block {
18 | return [CFAAction runBlock:block queue:dispatch_get_main_queue()];
19 | }
20 |
21 | + (CFAAction *)runBlock:(dispatch_block_t)block queue:(dispatch_queue_t)queue {
22 | CFARunBlock *runBlock = [[CFARunBlock alloc] init];
23 | runBlock->_block = (__bridge dispatch_block_t)Block_copy((__bridge void *)block);
24 | runBlock->_queue = queue;
25 | return runBlock;
26 | }
27 |
28 | - (id)copyWithZone:(NSZone *)zone {
29 | CFARunBlock *copiedAction = [super copyWithZone:zone];
30 | copiedAction->_block = (__bridge dispatch_block_t)Block_copy((__bridge void *)_block);
31 | copiedAction->_queue = _queue;
32 | return copiedAction;
33 | }
34 |
35 | - (CFAAction *)reversedAction {
36 | return [self copy];
37 | }
38 |
39 | - (void)executeWithTarget:(id)target forTime:(NSTimeInterval)time {
40 | if (self.finished) {
41 | return;
42 | }
43 | dispatch_async(_queue, _block);
44 | self.finished = YES;
45 | }
46 |
47 | @end
48 |
--------------------------------------------------------------------------------
/CFAAction/CFAScale.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFAScale.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFAScale : CFAAction
15 |
16 | + (CFAAction *)scaleBy:(CGFloat)scale duration:(NSTimeInterval)sec;
17 | + (CFAAction *)scaleXBy:(CGFloat)xScale y:(CGFloat)yScale duration:(NSTimeInterval)sec;
18 | + (CFAAction *)scaleTo:(CGFloat)scale duration:(NSTimeInterval)sec;
19 | + (CFAAction *)scaleXTo:(CGFloat)xScale y:(CGFloat)yScale duration:(NSTimeInterval)sec;
20 | + (CFAAction *)scaleXTo:(CGFloat)scale duration:(NSTimeInterval)sec;
21 | + (CFAAction *)scaleYTo:(CGFloat)scale duration:(NSTimeInterval)sec;
22 |
23 | @end
24 |
25 | NS_ASSUME_NONNULL_END
26 |
--------------------------------------------------------------------------------
/CFAAction/CFAScale.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFAScale.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAScale.h"
11 |
12 | static NSString *const CFAScaleKeypath = @"scale";
13 | static NSString *const CFAScaleXKeypath = @"transform.scale.x";
14 | static NSString *const CFAScaleYKeypath = @"transform.scale.y";
15 |
16 | typedef NS_ENUM(int, CFScaleSubtype) {
17 | CFScaleSubtypeNone = 0,
18 | CFScaleSubtypeDelta,
19 | CFScaleSubtypeDirect
20 | };
21 |
22 | @implementation CFAScale {
23 | CGFloat x, y;
24 | CFScaleSubtype _subtype;
25 | }
26 |
27 | + (CFAAction *)scaleBy:(CGFloat)scale duration:(NSTimeInterval)sec {
28 | return [CFAScale scaleXBy:scale y:scale duration:sec];
29 | }
30 |
31 | + (CFAAction *)scaleXBy:(CGFloat)xScale y:(CGFloat)yScale duration:(NSTimeInterval)sec {
32 | CFAScale *scaleAnimation = [[CFAScale alloc] init];
33 |
34 | scaleAnimation->x = xScale;
35 | scaleAnimation->y = yScale;
36 | scaleAnimation->_subtype = CFScaleSubtypeDelta;
37 | scaleAnimation.duration = sec;
38 |
39 | return scaleAnimation;
40 | }
41 |
42 | + (CFAAction *)scaleTo:(CGFloat)scale duration:(NSTimeInterval)sec {
43 | return [CFAScale scaleXTo:scale y:scale duration:sec];
44 | }
45 |
46 | + (CFAAction *)scaleXTo:(CGFloat)xScale y:(CGFloat)yScale duration:(NSTimeInterval)sec {
47 | CFAScale *scaleAnimation = [[CFAScale alloc] init];
48 |
49 | scaleAnimation->x = xScale;
50 | scaleAnimation->y = yScale;
51 | scaleAnimation->_subtype = CFScaleSubtypeDirect;
52 | scaleAnimation.duration = sec;
53 |
54 | return scaleAnimation;
55 | }
56 |
57 | + (CFAAction *)scaleXTo:(CGFloat)scale duration:(NSTimeInterval)sec {
58 | return [CFAScale scaleXBy:scale y:MAXFLOAT duration:sec];
59 | }
60 |
61 | + (CFAAction *)scaleYTo:(CGFloat)scale duration:(NSTimeInterval)sec {
62 | return [CFAScale scaleXBy:MAXFLOAT y:scale duration:sec];
63 | }
64 |
65 | - (id)copyWithZone:(NSZone *)zone {
66 | CFAScale *copiedAction = [super copyWithZone:zone];
67 | copiedAction->x = x;
68 | copiedAction->y = y;
69 | copiedAction->_subtype = _subtype;
70 | return copiedAction;
71 | }
72 |
73 | - (CFAAction *)reversedAction {
74 | if (_subtype == CFScaleSubtypeDirect) {
75 | return [self copy];
76 | }
77 | CFAScale *copiedAction = [super copyWithZone:NULL];
78 | copiedAction->x = -y;
79 | copiedAction->y = -x;
80 | copiedAction->_subtype = _subtype;
81 | return copiedAction;
82 | }
83 |
84 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
85 | float newX = CATransform3DGetAffineTransform(target.transform).a;
86 | float newY = CATransform3DGetAffineTransform(target.transform).b;
87 |
88 | switch (_subtype) {
89 | case CFScaleSubtypeDelta:
90 | if (x != MAXFLOAT) {
91 | newX += x;
92 | }
93 | if (y != MAXFLOAT) {
94 | newY += y;
95 | }
96 | break;
97 | case CFScaleSubtypeDirect:
98 | if (x != MAXFLOAT) {
99 | newX = x;
100 | }
101 | if (y != MAXFLOAT) {
102 | newY = y;
103 | }
104 | break;
105 | default:
106 | break;
107 | }
108 |
109 | CABasicAnimation *scaleX = [CABasicAnimation animationWithKeyPath:@"transform.scale.x"];
110 | scaleX.autoreverses = NO;
111 | scaleX.fromValue = [target.presentationLayer valueForKey:@"transform.scale.x"];
112 | scaleX.toValue = [NSNumber numberWithFloat:newX];
113 | scaleX.fillMode = kCAFillModeForwards;
114 | scaleX.removedOnCompletion = NO;
115 | scaleX.beginTime = time;
116 | scaleX.cumulative = YES;
117 | scaleX.timingFunction = self.timingFunction;
118 |
119 | CABasicAnimation *scaleY = [CABasicAnimation animationWithKeyPath:@"transform.scale.y"];
120 | scaleY.autoreverses = NO;
121 | scaleY.fromValue = [target.presentationLayer valueForKey:@"transform.scale.y"];
122 | scaleY.toValue = [NSNumber numberWithFloat:newY];
123 | scaleY.fillMode = kCAFillModeForwards;
124 | scaleY.removedOnCompletion = NO;
125 | scaleY.beginTime = time;
126 | scaleY.cumulative = YES;
127 | scaleY.timingFunction = self.timingFunction;
128 |
129 | [target addAnimation:scaleX forKey:CFAScaleXKeypath];
130 | [target addAnimation:scaleY forKey:CFAScaleYKeypath];
131 | }
132 |
133 | @end
134 |
--------------------------------------------------------------------------------
/CFAAction/CFASequence.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFASequence.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFASequence : CFAAction
15 |
16 | + (instancetype)sequenceWithActions:(NSArray *)actions;
17 |
18 | @end
19 |
20 | NS_ASSUME_NONNULL_END
21 |
--------------------------------------------------------------------------------
/CFAAction/CFASequence.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFASequence.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/16/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFASequence.h"
11 | #import "CFAGroup.h"
12 |
13 | @implementation CFASequence {
14 | NSArray *_actions;
15 | }
16 |
17 | - (id)init {
18 | self = [super init];
19 |
20 | _actions = [[NSArray alloc] init];
21 |
22 | return self;
23 | }
24 |
25 | + (instancetype)sequenceWithActions:(NSArray *)actions {
26 | CFASequence *sequence = nil;
27 | if (actions != nil) {
28 | if (actions.count != 0) {
29 | NSMutableArray *groupedActions = [[NSMutableArray alloc] initWithCapacity:actions.count];
30 | for (id action in actions) {
31 | if (![action isKindOfClass:NSArray.class]) {
32 | [groupedActions addObject:[action copy]];
33 | } else {
34 | [groupedActions addObject:[CFAGroup groupWithActions:action]];
35 | }
36 | }
37 | sequence = [[CFASequence alloc] init];
38 | sequence->_actions = groupedActions.copy;
39 | NSTimeInterval accumulator = 0.f;
40 | for (CFAGroup *group in groupedActions) {
41 | accumulator += group.duration;
42 | }
43 | [sequence setDuration:accumulator];
44 | }
45 | }
46 | return sequence;
47 | }
48 |
49 | - (id)copyWithZone:(NSZone *)zone {
50 | return [CFASequence sequenceWithActions:_actions];
51 | }
52 |
53 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
54 | NSTimeInterval accumulator = 0.0f;
55 | for (CFAAction *action in _actions) {
56 | [action executeWithTarget:target forTime:time + accumulator];
57 | accumulator += action.duration;
58 | }
59 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(accumulator * NSEC_PER_SEC));
60 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
61 | self.finished = YES;
62 | });
63 | }
64 |
65 | - (CFAAction *)reversedAction {
66 | NSMutableArray *reversedActions = [NSMutableArray arrayWithCapacity:_actions.count];
67 | for (CFAAction *action in _actions) {
68 | [reversedActions insertObject:[action reversedAction] atIndex:0];
69 | }
70 | return [CFASequence sequenceWithActions:reversedActions];
71 | }
72 |
73 | @end
74 |
--------------------------------------------------------------------------------
/CFAAction/CFASpeed.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFASpeed.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFASpeed : CFAAction
15 |
16 | + (CFAAction *)speedBy:(CGFloat)speed duration:(NSTimeInterval)sec;
17 | + (CFAAction *)speedTo:(CGFloat)speed duration:(NSTimeInterval)sec;
18 |
19 | @end
20 |
21 | NS_ASSUME_NONNULL_END
22 |
--------------------------------------------------------------------------------
/CFAAction/CFASpeed.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFASpeed.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFASpeed.h"
11 |
12 | static NSString *const CFASpeedKeypath = @"speed";
13 |
14 | typedef NS_ENUM(int, CFSpeedSubtype) {
15 | CFSpeedSubtypeNone = 0,
16 | CFSpeedSubtypeDelta,
17 | CFSpeedSubtypeDirect
18 | };
19 |
20 | @implementation CFASpeed {
21 | CGFloat _speed;
22 | CFSpeedSubtype _subtype;
23 | }
24 |
25 | + (CFAAction *)speedBy:(CGFloat)speed duration:(NSTimeInterval)sec {
26 | CFASpeed *speedAnimation = [[CFASpeed alloc] init];
27 |
28 | speedAnimation->_speed = speed;
29 | speedAnimation->_subtype = CFSpeedSubtypeDelta;
30 | speedAnimation.duration = sec;
31 |
32 | return speedAnimation;
33 | }
34 |
35 | + (CFAAction *)speedTo:(CGFloat)speed duration:(NSTimeInterval)sec {
36 | CFASpeed *speedAnimation = [[CFASpeed alloc] init];
37 |
38 | speedAnimation->_speed = speed;
39 | speedAnimation->_subtype = CFSpeedSubtypeDirect;
40 | speedAnimation.duration = sec;
41 |
42 | return speedAnimation;
43 | }
44 |
45 | - (id)copyWithZone:(NSZone *)zone {
46 | CFASpeed *copiedAction = [super copyWithZone:NULL];
47 | copiedAction->_speed = _speed;
48 | copiedAction->_subtype = _subtype;
49 | copiedAction.duration = self.duration;
50 | return copiedAction;
51 | }
52 |
53 | - (CFAAction *)reversedAction {
54 | CFASpeed *copiedAction = [super copyWithZone:NULL];
55 | copiedAction->_speed = -_speed;
56 | copiedAction->_subtype = _subtype;
57 | copiedAction.duration = self.duration;
58 | return copiedAction;
59 | }
60 |
61 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
62 | CGFloat newSpeed = [(CALayer *)target.presentationLayer ?: target speed];
63 |
64 | switch (_subtype) {
65 | case CFSpeedSubtypeDelta:
66 | newSpeed += _speed;
67 | break;
68 | case CFSpeedSubtypeDirect:
69 | newSpeed = _speed;
70 | break;
71 | default:
72 | break;
73 | }
74 |
75 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
76 | animation.removedOnCompletion = NO;
77 | animation.fillMode = kCAFillModeForwards;
78 | animation.beginTime = time;
79 | animation.fromValue = [(CALayer *)target.presentationLayer ?: target valueForKey:CFASpeedKeypath];
80 | animation.toValue = @(newSpeed);
81 | animation.duration = self.duration;
82 | animation.timingFunction = self.timingFunction;
83 | [animation setDelegate:self];
84 | [target.presentationLayer ?: target addAnimation:animation forKey:CFASpeedKeypath];
85 | }
86 |
87 | - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
88 | self.finished = YES;
89 | }
90 |
91 | @end
92 |
--------------------------------------------------------------------------------
/CFAAction/CFAWait.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFAWait.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAAction+Private.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface CFAWait : CFAAction
15 |
16 | + (CFAAction *)waitForDuration:(NSTimeInterval)sec;
17 | + (CFAAction *)waitForDuration:(NSTimeInterval)sec withRange:(NSTimeInterval)durationRange;
18 |
19 | @end
20 |
21 | NS_ASSUME_NONNULL_END
22 |
--------------------------------------------------------------------------------
/CFAAction/CFAWait.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFAWait.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import "CFAWait.h"
11 |
12 | @implementation CFAWait {
13 | NSTimeInterval _range;
14 | }
15 |
16 | + (CFAAction *)waitForDuration:(NSTimeInterval)sec {
17 | CFAWait *waitAnimation = [[CFAWait alloc] init];
18 |
19 | waitAnimation.duration = sec;
20 |
21 | return waitAnimation;
22 | }
23 |
24 | + (CFAAction *)waitForDuration:(NSTimeInterval)sec withRange:(NSTimeInterval)durationRange {
25 | CFAWait *waitAnimation = [[CFAWait alloc] init];
26 |
27 | waitAnimation->_range = durationRange;
28 | waitAnimation.duration = sec;
29 |
30 | return waitAnimation;
31 | }
32 |
33 | - (id)copyWithZone:(NSZone *)zone {
34 | CFAWait *copiedAction = [super copyWithZone:NULL];
35 | copiedAction->_range = _range;
36 | copiedAction.duration = self.duration;
37 | return copiedAction;
38 | }
39 |
40 | - (CFAAction *)reversedAction {
41 | return [self copy];
42 | }
43 |
44 | - (void)executeWithTarget:(CALayer *)target forTime:(NSTimeInterval)time {
45 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.duration * NSEC_PER_SEC));
46 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
47 | self.finished = YES;
48 | });
49 | }
50 |
51 |
52 | @end
53 |
--------------------------------------------------------------------------------
/CFAAction/NSBezierPath+CFABezierPathQuartzAssistant.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSBezierPath+CFABezierPathQuartzAssistant.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/18/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #import
11 |
12 | #if !(TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
13 |
14 | #import
15 |
16 | @interface NSBezierPath (CFABezierPathQuartzAssistant)
17 |
18 | - (CGPathRef)quartzPath;
19 |
20 | @end
21 |
22 | #endif
23 |
--------------------------------------------------------------------------------
/CFAAction/NSBezierPath+CFABezierPathQuartzAssistant.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSBezierPath+CFABezierPathQuartzAssistant.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/18/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | #if !(TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
11 |
12 | #import "NSBezierPath+CFABezierPathQuartzAssistant.h"
13 |
14 | @implementation NSBezierPath (BezierPathQuartzUtilities)
15 | // This method works only in OS X v10.2 and later.
16 | - (CGPathRef)quartzPath
17 | {
18 | NSInteger i, numElements;
19 |
20 | // Need to begin a path here.
21 | CGPathRef immutablePath = NULL;
22 |
23 | // Then draw the path elements.
24 | numElements = [self elementCount];
25 | if (numElements > 0)
26 | {
27 | CGMutablePathRef path = CGPathCreateMutable();
28 | NSPoint points[3];
29 | BOOL didClosePath = YES;
30 |
31 | for (i = 0; i < numElements; i++)
32 | {
33 | switch ([self elementAtIndex:i associatedPoints:points])
34 | {
35 | case NSMoveToBezierPathElement:
36 | CGPathMoveToPoint(path, NULL, points[0].x, points[0].y);
37 | break;
38 |
39 | case NSLineToBezierPathElement:
40 | CGPathAddLineToPoint(path, NULL, points[0].x, points[0].y);
41 | didClosePath = NO;
42 | break;
43 |
44 | case NSCurveToBezierPathElement:
45 | CGPathAddCurveToPoint(path, NULL, points[0].x, points[0].y,
46 | points[1].x, points[1].y,
47 | points[2].x, points[2].y);
48 | didClosePath = NO;
49 | break;
50 |
51 | case NSClosePathBezierPathElement:
52 | CGPathCloseSubpath(path);
53 | didClosePath = YES;
54 | break;
55 | }
56 | }
57 |
58 | // Be sure the path is closed or Quartz may not do valid hit detection.
59 | if (!didClosePath)
60 | CGPathCloseSubpath(path);
61 |
62 | immutablePath = CGPathCreateCopy(path);
63 | CGPathRelease(path);
64 | }
65 |
66 | return immutablePath;
67 | }
68 |
69 | @end
70 |
71 | #endif
72 |
--------------------------------------------------------------------------------
/CFAAction/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/CFAActionTests/CFAActionSpec.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFAActionSpec.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | // Released under the MIT license.
8 | //
9 |
10 | SpecBegin(CFAAction)
11 |
12 | __block Class CFAActionClass = Nil;
13 |
14 | describe(@"Convenience Initializers", ^{
15 | before(^{
16 | CFAActionClass = CFAAction.class;
17 | });
18 |
19 | it(@"should always dispense a subclass for move operations", ^{
20 | CFAAction *action = nil;
21 |
22 | action = [CFAAction moveByX:0 y:0 duration:0];
23 | expect(action.class).notTo.equal(CFAActionClass);
24 |
25 | #if CGVECTOR_DEFINED
26 | action = [CFAAction moveBy:(CGVector){ 0, 0 } duration:0];
27 | expect(action.class).notTo.equal(CFAActionClass);
28 | #endif
29 |
30 | action = [CFAAction moveTo:(CGPoint){ 0, 0 } duration:0];
31 | expect(action.class).notTo.equal(CFAActionClass);
32 |
33 | action = [CFAAction moveToX:0 duration:0];
34 | expect(action.class).notTo.equal(CFAActionClass);
35 |
36 | action = [CFAAction moveToY:0 duration:0];
37 | expect(action.class).notTo.equal(CFAActionClass);
38 | });
39 |
40 | it(@"should always dispense a subclass for rotate operations", ^{
41 | CFAAction *action = nil;
42 |
43 | action = [CFAAction rotateByAngle:0 duration: 0];
44 | expect(action.class).notTo.equal(CFAActionClass);
45 |
46 | action = [CFAAction rotateToAngle:0 duration: 0];
47 | expect(action.class).notTo.equal(CFAActionClass);
48 |
49 | action = [CFAAction rotateToAngle:0 duration: 0 shortestUnitArc:NO];
50 | expect(action.class).notTo.equal(CFAActionClass);
51 | });
52 |
53 | it(@"should always dispense a subclass for resize operations", ^{
54 | CFAAction *action = nil;
55 |
56 | action = [CFAAction resizeByWidth:0 height:0 duration:0];
57 | expect(action.class).notTo.equal(CFAActionClass);
58 |
59 | action = [CFAAction resizeToWidth:0 height:0 duration:0];
60 | expect(action.class).notTo.equal(CFAActionClass);
61 |
62 | action = [CFAAction resizeToWidth:0 duration:0];
63 | expect(action.class).notTo.equal(CFAActionClass);
64 |
65 | action = [CFAAction resizeToHeight:0 duration:0];
66 | expect(action.class).notTo.equal(CFAActionClass);
67 | });
68 |
69 | it(@"should always dispense a subclass for scale operations", ^{
70 | CFAAction *action = nil;
71 |
72 | action = [CFAAction scaleBy:0 duration: 0];
73 | expect(action.class).notTo.equal(CFAActionClass);
74 |
75 | action = [CFAAction scaleXBy:0 y:0 duration: 0];
76 | expect(action.class).notTo.equal(CFAActionClass);
77 |
78 | action = [CFAAction scaleTo:0 duration: 0];
79 | expect(action.class).notTo.equal(CFAActionClass);
80 |
81 | action = [CFAAction scaleXTo:0 y:0 duration: 0];
82 | expect(action.class).notTo.equal(CFAActionClass);
83 |
84 | action = [CFAAction scaleXTo:0 duration: 0];
85 | expect(action.class).notTo.equal(CFAActionClass);
86 |
87 | action = [CFAAction scaleYTo:0 duration: 0];
88 | expect(action.class).notTo.equal(CFAActionClass);
89 | });
90 |
91 | it(@"should always dispense a subclass for sequencing and grouping operations", ^{
92 | CFAAction *action = nil;
93 |
94 | action = [CFAAction sequence:@[]];
95 | expect(action.class).notTo.equal(CFAActionClass);
96 |
97 | action = [CFAAction group:@[]];
98 | expect(action.class).notTo.equal(CFAActionClass);
99 | });
100 |
101 | it(@"should always dispense a subclass for repeat operations", ^{
102 | CFAAction *action = nil;
103 |
104 | action = [CFAAction repeatAction:[CFAAction scaleBy:0 duration: 0] count:0];
105 | expect(action.class).notTo.equal(CFAActionClass);
106 |
107 | action = [CFAAction repeatActionForever:[CFAAction scaleBy:0 duration: 0]];
108 | expect(action.class).notTo.equal(CFAActionClass);
109 |
110 | });
111 |
112 | it(@"should always dispense a subclass for fade operations", ^{
113 | CFAAction *action = nil;
114 |
115 | action = [CFAAction fadeInWithDuration:0];
116 | expect(action.class).notTo.equal(CFAActionClass);
117 |
118 | action = [CFAAction fadeOutWithDuration:0];
119 | expect(action.class).notTo.equal(CFAActionClass);
120 |
121 | action = [CFAAction fadeAlphaBy:0 duration:0];
122 | expect(action.class).notTo.equal(CFAActionClass);
123 |
124 | action = [CFAAction fadeAlphaTo:0 duration:0];
125 | expect(action.class).notTo.equal(CFAActionClass);
126 | });
127 |
128 | it(@"should always dispense a subclass for path following operations", ^{
129 | CFAAction *action = nil;
130 | CGMutablePathRef path = CGPathCreateMutable();
131 |
132 | action = [CFAAction followPath:path duration:0];
133 | expect(action.class).notTo.equal(CFAActionClass);
134 |
135 | action = [CFAAction followPath:path asOffset:NO orientToPath:NO duration:0];
136 | expect(action.class).notTo.equal(CFAActionClass);
137 |
138 | CGPathRelease(path);
139 | });
140 |
141 | it(@"should always dispense a subclass for fade operations", ^{
142 | CFAAction *action = nil;
143 |
144 | action = [CFAAction speedBy:0 duration: 0];
145 | expect(action.class).notTo.equal(CFAActionClass);
146 |
147 | action = [CFAAction speedTo:0 duration: 0];
148 | expect(action.class).notTo.equal(CFAActionClass);
149 | });
150 |
151 | it(@"should always dispense a subclass for wait operations", ^{
152 | CFAAction *action = nil;
153 |
154 | action = [CFAAction waitForDuration:0];
155 | expect(action.class).notTo.equal(CFAActionClass);
156 |
157 | action = [CFAAction waitForDuration:0 withRange:0];
158 | expect(action.class).notTo.equal(CFAActionClass);
159 | });
160 |
161 | it(@"should always dispense a subclass for action operations", ^{
162 | CFAAction *action = nil;
163 |
164 | action = [CFAAction performSelector:@selector(description) onTarget:self];
165 | expect(action.class).notTo.equal(CFAActionClass);
166 |
167 | action = [CFAAction runBlock:^{ }];
168 | expect(action.class).notTo.equal(CFAActionClass);
169 |
170 | action = [CFAAction runBlock:^{ } queue:dispatch_get_main_queue()];
171 | expect(action.class).notTo.equal(CFAActionClass);
172 |
173 | action = [CFAAction customActionWithDuration:0 actionBlock:^(CALayer * _Nonnull node, CGFloat elapsedTime) { }];
174 | expect(action.class).notTo.equal(CFAActionClass);
175 | });
176 | });
177 |
178 | SpecEnd
--------------------------------------------------------------------------------
/CFAActionTests/CFAActionTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/CFAActionTests/CFAActionTests-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // CFAActionTests-Prefix.pch
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | //
8 |
9 | #ifndef CFAAction_CFAActionTests_Prefix_pch
10 | #define CFAAction_CFAActionTests_Prefix_pch
11 |
12 | #import
13 | #import
14 | #import
15 |
16 | #define EXP_SHORTHAND
17 | #import "Specta.h"
18 | #import "Expecta.h"
19 |
20 | #import "CFATestLayer.h"
21 |
22 | #endif
23 |
--------------------------------------------------------------------------------
/CFAActionTests/CFAPerformSelectorSpec.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFAPerformSelector.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 4/23/14.
6 | // Copyright (c) 2014 CodaFi. All rights reserved.
7 | //
8 |
9 | SpecBegin(CFAPerformSelector)
10 |
11 | static CGRect const CFITestLayerRect = (CGRect){ 100, 100, 100, 100 };
12 | __block CFATestLayer *layer = nil;
13 |
14 | describe(@"performSelector:onTarget:", ^{
15 | beforeEach(^{
16 | layer = CFATestLayer.layer;
17 | layer.frame = CFITestLayerRect;
18 | });
19 |
20 | it(@"should recieve a selector", ^{
21 | CFAAction *action = nil;
22 |
23 | expect(layer.gotIt).to.beFalsy();
24 | action = [CFAAction performSelector:@selector(knockKnock) onTarget:layer];
25 | [layer cfa_runAction:action completion:^{
26 | expect(layer.gotIt).to.beTruthy();
27 | }];
28 | });
29 | });
30 |
31 |
32 | SpecEnd
--------------------------------------------------------------------------------
/CFAActionTests/CFARunBlockSpec.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFARunBlockSpec.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 4/23/14.
6 | // Copyright (c) 2014 CodaFi. All rights reserved.
7 | //
8 |
9 | SpecBegin(CFARunBlock)
10 |
11 | static CGRect const CFITestLayerRect = (CGRect){ 100, 100, 100, 100 };
12 | __block CFATestLayer *layer = nil;
13 |
14 | describe(@"performSelector:onTarget:", ^{
15 | beforeEach(^{
16 | layer = CFATestLayer.layer;
17 | layer.frame = CFITestLayerRect;
18 | });
19 |
20 | it(@"should recieve a selector", ^{
21 | CFAAction *action = nil;
22 |
23 | expect(layer.gotIt).to.beFalsy();
24 | action = [CFAAction runBlock:^{
25 | [layer knockKnock];
26 | }];
27 | [layer cfa_runAction:action completion:^{
28 | expect(layer.gotIt).will.beTruthy();
29 | }];
30 | });
31 | });
32 |
33 |
34 | SpecEnd
--------------------------------------------------------------------------------
/CFAActionTests/CFATestLayer.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFATestLayer.h
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 4/23/14.
6 | // Copyright (c) 2014 CodaFi. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface CFATestLayer : CALayer
12 |
13 | - (void)knockKnock;
14 |
15 | @property (nonatomic) BOOL gotIt;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/CFAActionTests/CFATestLayer.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFATestLayer.m
3 | // CFAAction
4 | //
5 | // Created by Robert Widmann on 4/23/14.
6 | // Copyright (c) 2014 CodaFi. All rights reserved.
7 | //
8 |
9 | #import "CFATestLayer.h"
10 |
11 | @implementation CFATestLayer {
12 | CGRect _frame;
13 | }
14 |
15 | - (void)knockKnock {
16 | self.gotIt = YES;
17 | }
18 |
19 | - (void)setFrame:(CGRect)frame {
20 | _frame = frame;
21 | }
22 |
23 | - (CGRect)frame {
24 | return _frame;
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/CFAActionTests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Example/CAActionDemo/CAActionDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 84FE96E71810A5C5001BCD56 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FE96E61810A5C5001BCD56 /* Cocoa.framework */; };
11 | 84FE96F11810A5C5001BCD56 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 84FE96EF1810A5C5001BCD56 /* InfoPlist.strings */; };
12 | 84FE96F31810A5C5001BCD56 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 84FE96F21810A5C5001BCD56 /* main.m */; };
13 | 84FE96F71810A5C5001BCD56 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 84FE96F51810A5C5001BCD56 /* Credits.rtf */; };
14 | 84FE96FA1810A5C5001BCD56 /* CFIAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 84FE96F91810A5C5001BCD56 /* CFIAppDelegate.m */; };
15 | 84FE96FD1810A5C5001BCD56 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 84FE96FB1810A5C5001BCD56 /* MainMenu.xib */; };
16 | 84FE96FF1810A5C5001BCD56 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 84FE96FE1810A5C5001BCD56 /* Images.xcassets */; };
17 | 84FE97061810A5C5001BCD56 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FE97051810A5C5001BCD56 /* XCTest.framework */; };
18 | 84FE97071810A5C5001BCD56 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FE96E61810A5C5001BCD56 /* Cocoa.framework */; };
19 | 84FE97251810A5F7001BCD56 /* CFAAction.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FE97221810A5CC001BCD56 /* CFAAction.framework */; };
20 | 84FE97271810A688001BCD56 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FE97261810A688001BCD56 /* QuartzCore.framework */; };
21 | /* End PBXBuildFile section */
22 |
23 | /* Begin PBXContainerItemProxy section */
24 | 84FE97081810A5C5001BCD56 /* PBXContainerItemProxy */ = {
25 | isa = PBXContainerItemProxy;
26 | containerPortal = 84FE96DB1810A5C5001BCD56 /* Project object */;
27 | proxyType = 1;
28 | remoteGlobalIDString = 84FE96E21810A5C5001BCD56;
29 | remoteInfo = CAActionDemo;
30 | };
31 | 84FE97211810A5CC001BCD56 /* PBXContainerItemProxy */ = {
32 | isa = PBXContainerItemProxy;
33 | containerPortal = 84FE971A1810A5CB001BCD56 /* CFAAction.xcodeproj */;
34 | proxyType = 2;
35 | remoteGlobalIDString = 843FD48E180F38B6002CDEA7;
36 | remoteInfo = CFAAction;
37 | };
38 | 84FE97231810A5CC001BCD56 /* PBXContainerItemProxy */ = {
39 | isa = PBXContainerItemProxy;
40 | containerPortal = 84FE971A1810A5CB001BCD56 /* CFAAction.xcodeproj */;
41 | proxyType = 2;
42 | remoteGlobalIDString = 843FD4A5180F38B7002CDEA7;
43 | remoteInfo = CFAActionTests;
44 | };
45 | 84FE97281810A6BB001BCD56 /* PBXContainerItemProxy */ = {
46 | isa = PBXContainerItemProxy;
47 | containerPortal = 84FE971A1810A5CB001BCD56 /* CFAAction.xcodeproj */;
48 | proxyType = 1;
49 | remoteGlobalIDString = 843FD48D180F38B6002CDEA7;
50 | remoteInfo = CFAAction;
51 | };
52 | /* End PBXContainerItemProxy section */
53 |
54 | /* Begin PBXFileReference section */
55 | 84FE96E31810A5C5001BCD56 /* CAActionDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CAActionDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
56 | 84FE96E61810A5C5001BCD56 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
57 | 84FE96E91810A5C5001BCD56 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
58 | 84FE96EA1810A5C5001BCD56 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
59 | 84FE96EB1810A5C5001BCD56 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
60 | 84FE96EE1810A5C5001BCD56 /* CAActionDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CAActionDemo-Info.plist"; sourceTree = ""; };
61 | 84FE96F01810A5C5001BCD56 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
62 | 84FE96F21810A5C5001BCD56 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
63 | 84FE96F41810A5C5001BCD56 /* CAActionDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CAActionDemo-Prefix.pch"; sourceTree = ""; };
64 | 84FE96F61810A5C5001BCD56 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; };
65 | 84FE96F81810A5C5001BCD56 /* CFIAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CFIAppDelegate.h; sourceTree = ""; };
66 | 84FE96F91810A5C5001BCD56 /* CFIAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CFIAppDelegate.m; sourceTree = ""; };
67 | 84FE96FC1810A5C5001BCD56 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
68 | 84FE96FE1810A5C5001BCD56 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
69 | 84FE97041810A5C5001BCD56 /* CAActionDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CAActionDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
70 | 84FE97051810A5C5001BCD56 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
71 | 84FE971A1810A5CB001BCD56 /* CFAAction.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CFAAction.xcodeproj; path = ../../CFAAction.xcodeproj; sourceTree = ""; };
72 | 84FE97261810A688001BCD56 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
73 | /* End PBXFileReference section */
74 |
75 | /* Begin PBXFrameworksBuildPhase section */
76 | 84FE96E01810A5C5001BCD56 /* Frameworks */ = {
77 | isa = PBXFrameworksBuildPhase;
78 | buildActionMask = 2147483647;
79 | files = (
80 | 84FE97271810A688001BCD56 /* QuartzCore.framework in Frameworks */,
81 | 84FE97251810A5F7001BCD56 /* CFAAction.framework in Frameworks */,
82 | 84FE96E71810A5C5001BCD56 /* Cocoa.framework in Frameworks */,
83 | );
84 | runOnlyForDeploymentPostprocessing = 0;
85 | };
86 | 84FE97011810A5C5001BCD56 /* Frameworks */ = {
87 | isa = PBXFrameworksBuildPhase;
88 | buildActionMask = 2147483647;
89 | files = (
90 | 84FE97071810A5C5001BCD56 /* Cocoa.framework in Frameworks */,
91 | 84FE97061810A5C5001BCD56 /* XCTest.framework in Frameworks */,
92 | );
93 | runOnlyForDeploymentPostprocessing = 0;
94 | };
95 | /* End PBXFrameworksBuildPhase section */
96 |
97 | /* Begin PBXGroup section */
98 | 84FE96DA1810A5C5001BCD56 = {
99 | isa = PBXGroup;
100 | children = (
101 | 84FE971A1810A5CB001BCD56 /* CFAAction.xcodeproj */,
102 | 84FE96EC1810A5C5001BCD56 /* CAActionDemo */,
103 | 84FE96E51810A5C5001BCD56 /* Frameworks */,
104 | 84FE96E41810A5C5001BCD56 /* Products */,
105 | );
106 | sourceTree = "";
107 | };
108 | 84FE96E41810A5C5001BCD56 /* Products */ = {
109 | isa = PBXGroup;
110 | children = (
111 | 84FE96E31810A5C5001BCD56 /* CAActionDemo.app */,
112 | 84FE97041810A5C5001BCD56 /* CAActionDemoTests.xctest */,
113 | );
114 | name = Products;
115 | sourceTree = "";
116 | };
117 | 84FE96E51810A5C5001BCD56 /* Frameworks */ = {
118 | isa = PBXGroup;
119 | children = (
120 | 84FE97261810A688001BCD56 /* QuartzCore.framework */,
121 | 84FE96E61810A5C5001BCD56 /* Cocoa.framework */,
122 | 84FE97051810A5C5001BCD56 /* XCTest.framework */,
123 | 84FE96E81810A5C5001BCD56 /* Other Frameworks */,
124 | );
125 | name = Frameworks;
126 | sourceTree = "";
127 | };
128 | 84FE96E81810A5C5001BCD56 /* Other Frameworks */ = {
129 | isa = PBXGroup;
130 | children = (
131 | 84FE96E91810A5C5001BCD56 /* AppKit.framework */,
132 | 84FE96EA1810A5C5001BCD56 /* CoreData.framework */,
133 | 84FE96EB1810A5C5001BCD56 /* Foundation.framework */,
134 | );
135 | name = "Other Frameworks";
136 | sourceTree = "";
137 | };
138 | 84FE96EC1810A5C5001BCD56 /* CAActionDemo */ = {
139 | isa = PBXGroup;
140 | children = (
141 | 84FE96F81810A5C5001BCD56 /* CFIAppDelegate.h */,
142 | 84FE96F91810A5C5001BCD56 /* CFIAppDelegate.m */,
143 | 84FE96FB1810A5C5001BCD56 /* MainMenu.xib */,
144 | 84FE96FE1810A5C5001BCD56 /* Images.xcassets */,
145 | 84FE96ED1810A5C5001BCD56 /* Supporting Files */,
146 | );
147 | path = CAActionDemo;
148 | sourceTree = "";
149 | };
150 | 84FE96ED1810A5C5001BCD56 /* Supporting Files */ = {
151 | isa = PBXGroup;
152 | children = (
153 | 84FE96EE1810A5C5001BCD56 /* CAActionDemo-Info.plist */,
154 | 84FE96EF1810A5C5001BCD56 /* InfoPlist.strings */,
155 | 84FE96F21810A5C5001BCD56 /* main.m */,
156 | 84FE96F41810A5C5001BCD56 /* CAActionDemo-Prefix.pch */,
157 | 84FE96F51810A5C5001BCD56 /* Credits.rtf */,
158 | );
159 | name = "Supporting Files";
160 | sourceTree = "";
161 | };
162 | 84FE971B1810A5CB001BCD56 /* Products */ = {
163 | isa = PBXGroup;
164 | children = (
165 | 84FE97221810A5CC001BCD56 /* CFAAction.framework */,
166 | 84FE97241810A5CC001BCD56 /* CFAActionTests.octest */,
167 | );
168 | name = Products;
169 | sourceTree = "";
170 | };
171 | /* End PBXGroup section */
172 |
173 | /* Begin PBXNativeTarget section */
174 | 84FE96E21810A5C5001BCD56 /* CAActionDemo */ = {
175 | isa = PBXNativeTarget;
176 | buildConfigurationList = 84FE97141810A5C5001BCD56 /* Build configuration list for PBXNativeTarget "CAActionDemo" */;
177 | buildPhases = (
178 | 84FE96DF1810A5C5001BCD56 /* Sources */,
179 | 84FE96E01810A5C5001BCD56 /* Frameworks */,
180 | 84FE96E11810A5C5001BCD56 /* Resources */,
181 | );
182 | buildRules = (
183 | );
184 | dependencies = (
185 | 84FE97291810A6BB001BCD56 /* PBXTargetDependency */,
186 | );
187 | name = CAActionDemo;
188 | productName = CAActionDemo;
189 | productReference = 84FE96E31810A5C5001BCD56 /* CAActionDemo.app */;
190 | productType = "com.apple.product-type.application";
191 | };
192 | 84FE97031810A5C5001BCD56 /* CAActionDemoTests */ = {
193 | isa = PBXNativeTarget;
194 | buildConfigurationList = 84FE97171810A5C5001BCD56 /* Build configuration list for PBXNativeTarget "CAActionDemoTests" */;
195 | buildPhases = (
196 | 84FE97001810A5C5001BCD56 /* Sources */,
197 | 84FE97011810A5C5001BCD56 /* Frameworks */,
198 | 84FE97021810A5C5001BCD56 /* Resources */,
199 | );
200 | buildRules = (
201 | );
202 | dependencies = (
203 | 84FE97091810A5C5001BCD56 /* PBXTargetDependency */,
204 | );
205 | name = CAActionDemoTests;
206 | productName = CAActionDemoTests;
207 | productReference = 84FE97041810A5C5001BCD56 /* CAActionDemoTests.xctest */;
208 | productType = "com.apple.product-type.bundle.unit-test";
209 | };
210 | /* End PBXNativeTarget section */
211 |
212 | /* Begin PBXProject section */
213 | 84FE96DB1810A5C5001BCD56 /* Project object */ = {
214 | isa = PBXProject;
215 | attributes = {
216 | CLASSPREFIX = CFI;
217 | LastUpgradeCheck = 0500;
218 | ORGANIZATIONNAME = CodaFi;
219 | TargetAttributes = {
220 | 84FE97031810A5C5001BCD56 = {
221 | TestTargetID = 84FE96E21810A5C5001BCD56;
222 | };
223 | };
224 | };
225 | buildConfigurationList = 84FE96DE1810A5C5001BCD56 /* Build configuration list for PBXProject "CAActionDemo" */;
226 | compatibilityVersion = "Xcode 3.2";
227 | developmentRegion = English;
228 | hasScannedForEncodings = 0;
229 | knownRegions = (
230 | en,
231 | Base,
232 | );
233 | mainGroup = 84FE96DA1810A5C5001BCD56;
234 | productRefGroup = 84FE96E41810A5C5001BCD56 /* Products */;
235 | projectDirPath = "";
236 | projectReferences = (
237 | {
238 | ProductGroup = 84FE971B1810A5CB001BCD56 /* Products */;
239 | ProjectRef = 84FE971A1810A5CB001BCD56 /* CFAAction.xcodeproj */;
240 | },
241 | );
242 | projectRoot = "";
243 | targets = (
244 | 84FE96E21810A5C5001BCD56 /* CAActionDemo */,
245 | 84FE97031810A5C5001BCD56 /* CAActionDemoTests */,
246 | );
247 | };
248 | /* End PBXProject section */
249 |
250 | /* Begin PBXReferenceProxy section */
251 | 84FE97221810A5CC001BCD56 /* CFAAction.framework */ = {
252 | isa = PBXReferenceProxy;
253 | fileType = wrapper.framework;
254 | path = CFAAction.framework;
255 | remoteRef = 84FE97211810A5CC001BCD56 /* PBXContainerItemProxy */;
256 | sourceTree = BUILT_PRODUCTS_DIR;
257 | };
258 | 84FE97241810A5CC001BCD56 /* CFAActionTests.octest */ = {
259 | isa = PBXReferenceProxy;
260 | fileType = wrapper.cfbundle;
261 | path = CFAActionTests.octest;
262 | remoteRef = 84FE97231810A5CC001BCD56 /* PBXContainerItemProxy */;
263 | sourceTree = BUILT_PRODUCTS_DIR;
264 | };
265 | /* End PBXReferenceProxy section */
266 |
267 | /* Begin PBXResourcesBuildPhase section */
268 | 84FE96E11810A5C5001BCD56 /* Resources */ = {
269 | isa = PBXResourcesBuildPhase;
270 | buildActionMask = 2147483647;
271 | files = (
272 | 84FE96F11810A5C5001BCD56 /* InfoPlist.strings in Resources */,
273 | 84FE96FF1810A5C5001BCD56 /* Images.xcassets in Resources */,
274 | 84FE96F71810A5C5001BCD56 /* Credits.rtf in Resources */,
275 | 84FE96FD1810A5C5001BCD56 /* MainMenu.xib in Resources */,
276 | );
277 | runOnlyForDeploymentPostprocessing = 0;
278 | };
279 | 84FE97021810A5C5001BCD56 /* Resources */ = {
280 | isa = PBXResourcesBuildPhase;
281 | buildActionMask = 2147483647;
282 | files = (
283 | );
284 | runOnlyForDeploymentPostprocessing = 0;
285 | };
286 | /* End PBXResourcesBuildPhase section */
287 |
288 | /* Begin PBXSourcesBuildPhase section */
289 | 84FE96DF1810A5C5001BCD56 /* Sources */ = {
290 | isa = PBXSourcesBuildPhase;
291 | buildActionMask = 2147483647;
292 | files = (
293 | 84FE96F31810A5C5001BCD56 /* main.m in Sources */,
294 | 84FE96FA1810A5C5001BCD56 /* CFIAppDelegate.m in Sources */,
295 | );
296 | runOnlyForDeploymentPostprocessing = 0;
297 | };
298 | 84FE97001810A5C5001BCD56 /* Sources */ = {
299 | isa = PBXSourcesBuildPhase;
300 | buildActionMask = 2147483647;
301 | files = (
302 | );
303 | runOnlyForDeploymentPostprocessing = 0;
304 | };
305 | /* End PBXSourcesBuildPhase section */
306 |
307 | /* Begin PBXTargetDependency section */
308 | 84FE97091810A5C5001BCD56 /* PBXTargetDependency */ = {
309 | isa = PBXTargetDependency;
310 | target = 84FE96E21810A5C5001BCD56 /* CAActionDemo */;
311 | targetProxy = 84FE97081810A5C5001BCD56 /* PBXContainerItemProxy */;
312 | };
313 | 84FE97291810A6BB001BCD56 /* PBXTargetDependency */ = {
314 | isa = PBXTargetDependency;
315 | name = CFAAction;
316 | targetProxy = 84FE97281810A6BB001BCD56 /* PBXContainerItemProxy */;
317 | };
318 | /* End PBXTargetDependency section */
319 |
320 | /* Begin PBXVariantGroup section */
321 | 84FE96EF1810A5C5001BCD56 /* InfoPlist.strings */ = {
322 | isa = PBXVariantGroup;
323 | children = (
324 | 84FE96F01810A5C5001BCD56 /* en */,
325 | );
326 | name = InfoPlist.strings;
327 | sourceTree = "";
328 | };
329 | 84FE96F51810A5C5001BCD56 /* Credits.rtf */ = {
330 | isa = PBXVariantGroup;
331 | children = (
332 | 84FE96F61810A5C5001BCD56 /* en */,
333 | );
334 | name = Credits.rtf;
335 | sourceTree = "";
336 | };
337 | 84FE96FB1810A5C5001BCD56 /* MainMenu.xib */ = {
338 | isa = PBXVariantGroup;
339 | children = (
340 | 84FE96FC1810A5C5001BCD56 /* Base */,
341 | );
342 | name = MainMenu.xib;
343 | sourceTree = "";
344 | };
345 | /* End PBXVariantGroup section */
346 |
347 | /* Begin XCBuildConfiguration section */
348 | 84FE97121810A5C5001BCD56 /* Debug */ = {
349 | isa = XCBuildConfiguration;
350 | buildSettings = {
351 | ALWAYS_SEARCH_USER_PATHS = NO;
352 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
353 | CLANG_CXX_LIBRARY = "libc++";
354 | CLANG_ENABLE_OBJC_ARC = YES;
355 | CLANG_WARN_BOOL_CONVERSION = YES;
356 | CLANG_WARN_CONSTANT_CONVERSION = YES;
357 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
358 | CLANG_WARN_EMPTY_BODY = YES;
359 | CLANG_WARN_ENUM_CONVERSION = YES;
360 | CLANG_WARN_INT_CONVERSION = YES;
361 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
362 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
363 | COPY_PHASE_STRIP = NO;
364 | GCC_C_LANGUAGE_STANDARD = gnu99;
365 | GCC_DYNAMIC_NO_PIC = NO;
366 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
367 | GCC_OPTIMIZATION_LEVEL = 0;
368 | GCC_PREPROCESSOR_DEFINITIONS = (
369 | "DEBUG=1",
370 | "$(inherited)",
371 | );
372 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
373 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
374 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
375 | GCC_WARN_UNDECLARED_SELECTOR = YES;
376 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
377 | GCC_WARN_UNUSED_FUNCTION = YES;
378 | GCC_WARN_UNUSED_VARIABLE = YES;
379 | MACOSX_DEPLOYMENT_TARGET = 10.9;
380 | ONLY_ACTIVE_ARCH = YES;
381 | SDKROOT = macosx;
382 | };
383 | name = Debug;
384 | };
385 | 84FE97131810A5C5001BCD56 /* Release */ = {
386 | isa = XCBuildConfiguration;
387 | buildSettings = {
388 | ALWAYS_SEARCH_USER_PATHS = NO;
389 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
390 | CLANG_CXX_LIBRARY = "libc++";
391 | CLANG_ENABLE_OBJC_ARC = YES;
392 | CLANG_WARN_BOOL_CONVERSION = YES;
393 | CLANG_WARN_CONSTANT_CONVERSION = YES;
394 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
395 | CLANG_WARN_EMPTY_BODY = YES;
396 | CLANG_WARN_ENUM_CONVERSION = YES;
397 | CLANG_WARN_INT_CONVERSION = YES;
398 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
399 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
400 | COPY_PHASE_STRIP = YES;
401 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
402 | ENABLE_NS_ASSERTIONS = NO;
403 | GCC_C_LANGUAGE_STANDARD = gnu99;
404 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
405 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
406 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
407 | GCC_WARN_UNDECLARED_SELECTOR = YES;
408 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
409 | GCC_WARN_UNUSED_FUNCTION = YES;
410 | GCC_WARN_UNUSED_VARIABLE = YES;
411 | MACOSX_DEPLOYMENT_TARGET = 10.9;
412 | SDKROOT = macosx;
413 | };
414 | name = Release;
415 | };
416 | 84FE97151810A5C5001BCD56 /* Debug */ = {
417 | isa = XCBuildConfiguration;
418 | buildSettings = {
419 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
420 | COMBINE_HIDPI_IMAGES = YES;
421 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
422 | GCC_PREFIX_HEADER = "CAActionDemo/CAActionDemo-Prefix.pch";
423 | INFOPLIST_FILE = "CAActionDemo/CAActionDemo-Info.plist";
424 | MACOSX_DEPLOYMENT_TARGET = 10.8;
425 | PRODUCT_NAME = "$(TARGET_NAME)";
426 | WRAPPER_EXTENSION = app;
427 | };
428 | name = Debug;
429 | };
430 | 84FE97161810A5C5001BCD56 /* Release */ = {
431 | isa = XCBuildConfiguration;
432 | buildSettings = {
433 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
434 | COMBINE_HIDPI_IMAGES = YES;
435 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
436 | GCC_PREFIX_HEADER = "CAActionDemo/CAActionDemo-Prefix.pch";
437 | INFOPLIST_FILE = "CAActionDemo/CAActionDemo-Info.plist";
438 | MACOSX_DEPLOYMENT_TARGET = 10.8;
439 | PRODUCT_NAME = "$(TARGET_NAME)";
440 | WRAPPER_EXTENSION = app;
441 | };
442 | name = Release;
443 | };
444 | 84FE97181810A5C5001BCD56 /* Debug */ = {
445 | isa = XCBuildConfiguration;
446 | buildSettings = {
447 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/CAActionDemo.app/Contents/MacOS/CAActionDemo";
448 | COMBINE_HIDPI_IMAGES = YES;
449 | FRAMEWORK_SEARCH_PATHS = (
450 | "$(DEVELOPER_FRAMEWORKS_DIR)",
451 | "$(inherited)",
452 | );
453 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
454 | GCC_PREFIX_HEADER = "CAActionDemo/CAActionDemo-Prefix.pch";
455 | GCC_PREPROCESSOR_DEFINITIONS = (
456 | "DEBUG=1",
457 | "$(inherited)",
458 | );
459 | INFOPLIST_FILE = "CAActionDemoTests/CAActionDemoTests-Info.plist";
460 | MACOSX_DEPLOYMENT_TARGET = 10.8;
461 | PRODUCT_NAME = "$(TARGET_NAME)";
462 | TEST_HOST = "$(BUNDLE_LOADER)";
463 | WRAPPER_EXTENSION = xctest;
464 | };
465 | name = Debug;
466 | };
467 | 84FE97191810A5C5001BCD56 /* Release */ = {
468 | isa = XCBuildConfiguration;
469 | buildSettings = {
470 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/CAActionDemo.app/Contents/MacOS/CAActionDemo";
471 | COMBINE_HIDPI_IMAGES = YES;
472 | FRAMEWORK_SEARCH_PATHS = (
473 | "$(DEVELOPER_FRAMEWORKS_DIR)",
474 | "$(inherited)",
475 | );
476 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
477 | GCC_PREFIX_HEADER = "CAActionDemo/CAActionDemo-Prefix.pch";
478 | INFOPLIST_FILE = "CAActionDemoTests/CAActionDemoTests-Info.plist";
479 | MACOSX_DEPLOYMENT_TARGET = 10.8;
480 | PRODUCT_NAME = "$(TARGET_NAME)";
481 | TEST_HOST = "$(BUNDLE_LOADER)";
482 | WRAPPER_EXTENSION = xctest;
483 | };
484 | name = Release;
485 | };
486 | /* End XCBuildConfiguration section */
487 |
488 | /* Begin XCConfigurationList section */
489 | 84FE96DE1810A5C5001BCD56 /* Build configuration list for PBXProject "CAActionDemo" */ = {
490 | isa = XCConfigurationList;
491 | buildConfigurations = (
492 | 84FE97121810A5C5001BCD56 /* Debug */,
493 | 84FE97131810A5C5001BCD56 /* Release */,
494 | );
495 | defaultConfigurationIsVisible = 0;
496 | defaultConfigurationName = Release;
497 | };
498 | 84FE97141810A5C5001BCD56 /* Build configuration list for PBXNativeTarget "CAActionDemo" */ = {
499 | isa = XCConfigurationList;
500 | buildConfigurations = (
501 | 84FE97151810A5C5001BCD56 /* Debug */,
502 | 84FE97161810A5C5001BCD56 /* Release */,
503 | );
504 | defaultConfigurationIsVisible = 0;
505 | defaultConfigurationName = Release;
506 | };
507 | 84FE97171810A5C5001BCD56 /* Build configuration list for PBXNativeTarget "CAActionDemoTests" */ = {
508 | isa = XCConfigurationList;
509 | buildConfigurations = (
510 | 84FE97181810A5C5001BCD56 /* Debug */,
511 | 84FE97191810A5C5001BCD56 /* Release */,
512 | );
513 | defaultConfigurationIsVisible = 0;
514 | defaultConfigurationName = Release;
515 | };
516 | /* End XCConfigurationList section */
517 | };
518 | rootObject = 84FE96DB1810A5C5001BCD56 /* Project object */;
519 | }
520 |
--------------------------------------------------------------------------------
/Example/CAActionDemo/CAActionDemo/Base.lproj/MainMenu.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
--------------------------------------------------------------------------------
/Example/CAActionDemo/CAActionDemo/CAActionDemo-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | com.codafi.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSMinimumSystemVersion
26 | ${MACOSX_DEPLOYMENT_TARGET}
27 | NSHumanReadableCopyright
28 | Copyright © 2013 CodaFi. All rights reserved.
29 | NSMainNibFile
30 | MainMenu
31 | NSPrincipalClass
32 | NSApplication
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Example/CAActionDemo/CAActionDemo/CAActionDemo-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header
3 | //
4 | // The contents of this file are implicitly included at the beginning of every source file.
5 | //
6 |
7 | #ifdef __OBJC__
8 | #import
9 | #import
10 | #endif
11 |
--------------------------------------------------------------------------------
/Example/CAActionDemo/CAActionDemo/CFIAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFIAppDelegate.h
3 | // CAActionDemo
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface CFIAppDelegate : NSObject
12 |
13 | @property (assign) IBOutlet NSWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Example/CAActionDemo/CAActionDemo/CFIAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFIAppDelegate.m
3 | // CAActionDemo
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | //
8 |
9 | #import "CFIAppDelegate.h"
10 | #import
11 |
12 | @interface CFIAppDelegate ()
13 |
14 | @property (nonatomic, strong) CALayer *greenLayer;
15 | @property (nonatomic, strong) CALayer *redLayer;
16 | @property (nonatomic, strong) CALayer *yellowLayer;
17 |
18 | @end
19 |
20 | @implementation CFIAppDelegate
21 |
22 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
23 | _greenLayer = CALayer.layer;
24 | _greenLayer.frame = CGRectMake(-200, NSMidY([self.window.contentView frame]) - 50, 100, 100);
25 | _greenLayer.backgroundColor = [NSColor.greenColor CGColor];
26 | _greenLayer.anchorPoint = CGPointMake(0.5, 0.5);
27 |
28 | _redLayer = CALayer.layer;
29 | _redLayer.frame = CGRectMake(NSMidX([self.window.contentView frame]) - 50, NSMidY([self.window.contentView frame]) - 50, 100, 100);
30 | _redLayer.backgroundColor = [NSColor.redColor CGColor];
31 | _redLayer.anchorPoint = CGPointMake(0.5, 0.5);
32 |
33 | _yellowLayer = CALayer.layer;
34 | _yellowLayer.frame = CGRectMake(850, NSMidY([self.window.contentView frame]) - 50, 100, 100);
35 | _yellowLayer.backgroundColor = [NSColor.yellowColor CGColor];
36 | _yellowLayer.anchorPoint = CGPointMake(0.5, 0.5);
37 |
38 | [[self.window.contentView layer] addSublayer:_greenLayer];
39 | [[self.window.contentView layer] addSublayer:_redLayer];
40 | [[self.window.contentView layer] addSublayer:_yellowLayer];
41 |
42 | CFAAction *moveAction = [CFAAction moveByX:250 y:0 duration:1];
43 | CFAAction *rotateAction = [CFAAction rotateToAngle:M_PI duration:1];
44 | CFAAction *scaleAnimation = [CFAAction scaleBy:-0.25 duration:0.25];
45 | CFAAction *growAnimation = [CFAAction resizeToHeight:400 duration:0.25];
46 |
47 | [self.redLayer runAction:[CFAAction repeatAction:rotateAction count:7] completion:^{
48 | [self.redLayer runAction:growAnimation];
49 | }];
50 |
51 | [self.greenLayer runAction:[CFAAction waitForDuration:0.5] completion:^{
52 | [self.greenLayer runAction:[CFAAction sequence:@[ moveAction, [CFAAction repeatAction:rotateAction count:6], growAnimation ]] completion:^{
53 | [self.greenLayer runAction:scaleAnimation];
54 | }];
55 | }];
56 |
57 | [self.yellowLayer runAction:[CFAAction waitForDuration:0.5] completion:^{
58 | [self.yellowLayer runAction:[CFAAction sequence:@[ [moveAction reversedAction], [CFAAction repeatAction:rotateAction count:6], growAnimation ]] completion:^{
59 | [self.yellowLayer runAction:scaleAnimation];
60 | }];
61 | }];
62 | }
63 |
64 | @end
65 |
--------------------------------------------------------------------------------
/Example/CAActionDemo/CAActionDemo/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "size" : "16x16",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "size" : "16x16",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "size" : "32x32",
16 | "scale" : "1x"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "size" : "32x32",
21 | "scale" : "2x"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "size" : "128x128",
26 | "scale" : "1x"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "size" : "128x128",
31 | "scale" : "2x"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "size" : "256x256",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "size" : "256x256",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "size" : "512x512",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "size" : "512x512",
51 | "scale" : "2x"
52 | }
53 | ],
54 | "info" : {
55 | "version" : 1,
56 | "author" : "xcode"
57 | }
58 | }
--------------------------------------------------------------------------------
/Example/CAActionDemo/CAActionDemo/en.lproj/Credits.rtf:
--------------------------------------------------------------------------------
1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
2 | {\colortbl;\red255\green255\blue255;}
3 | \paperw9840\paperh8400
4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
5 |
6 | \f0\b\fs24 \cf0 Engineering:
7 | \b0 \
8 | Some people\
9 | \
10 |
11 | \b Human Interface Design:
12 | \b0 \
13 | Some other people\
14 | \
15 |
16 | \b Testing:
17 | \b0 \
18 | Hopefully not nobody\
19 | \
20 |
21 | \b Documentation:
22 | \b0 \
23 | Whoever\
24 | \
25 |
26 | \b With special thanks to:
27 | \b0 \
28 | Mom\
29 | }
30 |
--------------------------------------------------------------------------------
/Example/CAActionDemo/CAActionDemo/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Example/CAActionDemo/CAActionDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // CAActionDemo
4 | //
5 | // Created by Robert Widmann on 10/17/13.
6 | // Copyright (c) 2013 CodaFi. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | int main(int argc, const char * argv[])
12 | {
13 | return NSApplicationMain(argc, argv);
14 | }
15 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 Robert Widmann
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## CFAAction ##
2 |
3 | [](https://travis-ci.org/CodaFi/CFAAction)
4 |
5 | `CFAAction` is a wrapper around several common Core Animation animations that provides additional modularity and the ability to group and sequence actions.
6 |
7 | ## Getting Started
8 | `CFAAction`'s should be treated like `SKAction`'s, which means they are only run when they are submitted to a variant of `-[CALayer runAction:]`.
9 |
10 | To run an action that moves a layer 10 pixels to the right in 1 second, for example, you can do:
11 |
12 | ```Objective-C
13 | CFAAction *moveAction = [CFAAction moveByX:10 y:0 duration:1];
14 | [self.view.layer runAction:growAnimation];
15 | ```
16 | Completion blocks can be used to sequence animations:
17 |
18 | ```Objective-C
19 | CFAAction *rotateAction = [CFAAction rotateToAngle:M_PI duration:1];
20 | CFAAction *growAnimation = [CFAAction resizeToHeight:400 duration:0.25];
21 |
22 | [self.view.layer runAction:rotateAction completion:^{
23 | [self.view.layer runAction:growAnimation];
24 | }];
25 | ```
26 |
27 | But, so can `+[CFAAction sequence:]`:
28 |
29 | ```Objective-C
30 | CFAAction *rotateAction = [CFAAction rotateToAngle:M_PI duration:1];
31 | CFAAction *growAnimation = [CFAAction resizeToHeight:400 duration:0.25];
32 |
33 | [self.view.layer runAction:[CFAAction sequence:@[ rotateAction, growAnimation ]];
34 | ```
35 |
36 | To run actions concurrently, there's `+[CFAAction group:]`:
37 |
38 | ```Objective-C
39 | CFAAction *rotateAction = [CFAAction rotateToAngle:M_PI duration:1];
40 | CFAAction *scaleAnimation = [CFAAction scaleBy:-0.25 duration:0.25];
41 | [self.view.layer runAction:[CFAAction group:@[ scaleAnimation, rotateAction ]]];
42 | ```
43 |
44 | To perform a block or selector as an action, use `[CFAAnimation runBlock:]`, `[CFAAnimation runBlock:queue:]`, or `[CFAAnimation performSelector:onTarget:]`. When used in a group with a wait action, these can act as extensions for the total duration of the grouping. When used in a sequence, they can act as delays before or after the selector is performed for precision timing.
45 |
46 | ```Objective-C
47 | [self.planeLayer runAction:[CFAAction sequence:@[ bankAndRollAction, [CFAAction repeatAction:fireAction count:6] ]] completion:^{
48 | [self.enemy runAction:[CFAAction sequence:@[ dieAction, [CFAAction performSelector:@selector(die:) onTarget:self.enemy], [CFAAction waitForDuration:0.5] ]]];
49 | }];
50 | ```
51 | ## License ##
52 | `CFAAction` is licensed under the [MIT](http://opensource.org/licenses/MIT) license. See [LICENSE.md](LICENSE.md).
53 |
54 | ## Contact ##
55 | Follow me on Twitter [@CodaFi_](https://twitter.com/CodaFi_), or visit [my website](http://λπω.com/).
--------------------------------------------------------------------------------