Skip to content

Instantly share code, notes, and snippets.

@nevyn
Created June 23, 2013 06:37
Show Gist options
  • Save nevyn/5844046 to your computer and use it in GitHub Desktop.
Save nevyn/5844046 to your computer and use it in GitHub Desktop.
How to wait for multiple different-timed animations in a generic manner? A reply to http://inessential.com/2013/06/22/technical_notes_on_vespers_full-scree .
#import "TCAppDelegate.h"
// Let's use https://github.com/nevyn/SPAsync
#import <SPAsync/SPTask.h>
@interface UIView (SPTaskAnimations)
// Category that returns an abstraction representing an asynchronous operation, rather than just a raw block. We can use this abstraction later to compose multiple of them.
+ (SPTask*)task_animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations;
@end
static UIView *coloredView(UIColor *color, CGPoint position);
@implementation TCAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
UIView *red = coloredView([UIColor redColor], CGPointMake(60, 30));
UIView *gre = coloredView([UIColor greenColor], CGPointMake(20, 200));
UIView *blu = coloredView([UIColor blueColor], CGPointMake(220, 40));
[self.window addSubview:red];
[self.window addSubview:gre];
[self.window addSubview:blu];
// Let's wait for multiple things to finish.
[[[SPTask awaitAll:@[
// Create three different asynchronous operations.
[UIView task_animateWithDuration:.9 delay:1 options:0 animations:^{
red.center = CGPointMake(170, 180);
}],
[UIView task_animateWithDuration:.4 delay:1 options:0 animations:^{
gre.center = CGPointMake(120, 220);
}],
[UIView task_animateWithDuration:1.5 delay:1 options:0 animations:^{
blu.center = CGPointMake(220, 220);
}],
// Add a callback to when all three tasks have finished. Make that callback return yet another thing to wait for (a fade-out)
]] chain:^SPTask *(id value) {
return [UIView task_animateWithDuration:.5 delay:1.5 options:0 animations:^{
red.alpha = gre.alpha = blu.alpha = 0;
}];
// Add a callback to when that one has finished as well.
} on:dispatch_get_main_queue()] addCallback:^(id value) {
NSLog(@"All done!");
}];
// We could have accomplished the same thing by using NSOperation and adding dependencies between them. I'm not sure which one I prefer.
return YES;
}
@end
@implementation UIView (SPTaskAnimations)
+ (SPTask*)task_animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations
{
SPTaskCompletionSource *source = [SPTaskCompletionSource new];
[self animateWithDuration:duration delay:delay options:options animations:animations completion:^(BOOL finished) {
[source completeWithValue:@(finished)];
}];
return source.task;
}
@end
static UIView *coloredView(UIColor *color, CGPoint position)
{
UIView *v = [[UIView alloc] initWithFrame:(CGRect){.origin = position, .size = {20, 20}}];
v.backgroundColor = color;
return v;
}
@dinhvh
Copy link

dinhvh commented Jun 23, 2013

There's probably a need for a "meta"-language to describe a multi-step animation on iOS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment