From 7f1666f6dce96edd912ce54999069d128e2cc9da Mon Sep 17 00:00:00 2001 From: miyakeryo Date: Tue, 25 Aug 2015 11:10:14 +0900 Subject: [PATCH] Add method chaining --- Demo/GLDTween.xcodeproj/project.pbxproj | 26 ++ .../TouchDemo/TouchDemoViewController.m | 38 +- GLDTween/GLDTween+Chain.h | 16 + GLDTween/GLDTween+Chain.m | 20 + GLDTween/GLDTweenChain.h | 52 +++ GLDTween/GLDTweenChain.m | 372 ++++++++++++++++++ GLDTween/GLDTweenChainAction.h | 37 ++ GLDTween/GLDTweenChainAction.m | 165 ++++++++ 8 files changed, 725 insertions(+), 1 deletion(-) create mode 100644 GLDTween/GLDTween+Chain.h create mode 100644 GLDTween/GLDTween+Chain.m create mode 100644 GLDTween/GLDTweenChain.h create mode 100644 GLDTween/GLDTweenChain.m create mode 100644 GLDTween/GLDTweenChainAction.h create mode 100644 GLDTween/GLDTweenChainAction.m diff --git a/Demo/GLDTween.xcodeproj/project.pbxproj b/Demo/GLDTween.xcodeproj/project.pbxproj index b228e28..060e49a 100644 --- a/Demo/GLDTween.xcodeproj/project.pbxproj +++ b/Demo/GLDTween.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 117AB29E1B8BECDB00CD92C7 /* GLDTweenChain.m in Sources */ = {isa = PBXBuildFile; fileRef = 117AB29B1B8BECDB00CD92C7 /* GLDTweenChain.m */; }; + 117AB29F1B8BECDB00CD92C7 /* GLDTweenChainAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 117AB29D1B8BECDB00CD92C7 /* GLDTweenChainAction.m */; }; + 117AB2A21B8BED0800CD92C7 /* GLDTween+Chain.m in Sources */ = {isa = PBXBuildFile; fileRef = 117AB2A11B8BED0800CD92C7 /* GLDTween+Chain.m */; }; 3D5366F519DC31D10017C6B8 /* GLDTweenSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D5366F419DC31D10017C6B8 /* GLDTweenSelector.m */; }; 3D5366F819DC337F0017C6B8 /* GLDTweenBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D5366F719DC337F0017C6B8 /* GLDTweenBlock.m */; }; 3D53670C19DE16270017C6B8 /* TouchDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D53670B19DE16270017C6B8 /* TouchDemoViewController.m */; }; @@ -34,6 +37,12 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 117AB29A1B8BECDB00CD92C7 /* GLDTweenChain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GLDTweenChain.h; path = ../../GLDTween/GLDTweenChain.h; sourceTree = ""; }; + 117AB29B1B8BECDB00CD92C7 /* GLDTweenChain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GLDTweenChain.m; path = ../../GLDTween/GLDTweenChain.m; sourceTree = ""; }; + 117AB29C1B8BECDB00CD92C7 /* GLDTweenChainAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GLDTweenChainAction.h; path = ../../GLDTween/GLDTweenChainAction.h; sourceTree = ""; }; + 117AB29D1B8BECDB00CD92C7 /* GLDTweenChainAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GLDTweenChainAction.m; path = ../../GLDTween/GLDTweenChainAction.m; sourceTree = ""; }; + 117AB2A01B8BED0800CD92C7 /* GLDTween+Chain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "GLDTween+Chain.h"; path = "../../GLDTween/GLDTween+Chain.h"; sourceTree = ""; }; + 117AB2A11B8BED0800CD92C7 /* GLDTween+Chain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "GLDTween+Chain.m"; path = "../../GLDTween/GLDTween+Chain.m"; sourceTree = ""; }; 3D5366F319DC31D10017C6B8 /* GLDTweenSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = GLDTweenSelector.h; path = ../../GLDTween/GLDTweenSelector.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 3D5366F419DC31D10017C6B8 /* GLDTweenSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = GLDTweenSelector.m; path = ../../GLDTween/GLDTweenSelector.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 3D5366F619DC337F0017C6B8 /* GLDTweenBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = GLDTweenBlock.h; path = ../../GLDTween/GLDTweenBlock.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; @@ -81,6 +90,19 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 117AB2A31B8BEF8400CD92C7 /* chain */ = { + isa = PBXGroup; + children = ( + 117AB2A01B8BED0800CD92C7 /* GLDTween+Chain.h */, + 117AB2A11B8BED0800CD92C7 /* GLDTween+Chain.m */, + 117AB29A1B8BECDB00CD92C7 /* GLDTweenChain.h */, + 117AB29B1B8BECDB00CD92C7 /* GLDTweenChain.m */, + 117AB29C1B8BECDB00CD92C7 /* GLDTweenChainAction.h */, + 117AB29D1B8BECDB00CD92C7 /* GLDTweenChainAction.m */, + ); + name = chain; + sourceTree = ""; + }; 3D53670219DD57610017C6B8 /* Sample */ = { isa = PBXGroup; children = ( @@ -164,6 +186,7 @@ 3DAE9D4419DB9DA0003692A1 /* GLDTween.m */, 3DAE9D4A19DBA6D4003692A1 /* core */, 3DAE9D4919DBA11D003692A1 /* plugins */, + 117AB2A31B8BEF8400CD92C7 /* chain */, ); name = GLDTween; sourceTree = ""; @@ -301,9 +324,12 @@ 3DAE9D1F19DB9D30003692A1 /* main.m in Sources */, 3DAE9D4D19DBB3C9003692A1 /* GLDTweenProperty.m in Sources */, 3DAE9D4519DB9DA0003692A1 /* GLDTween.m in Sources */, + 117AB29E1B8BECDB00CD92C7 /* GLDTweenChain.m in Sources */, 3D53675519DEE4550017C6B8 /* GLDTweenPropertyPlugin.m in Sources */, + 117AB2A21B8BED0800CD92C7 /* GLDTween+Chain.m in Sources */, 3D5366F819DC337F0017C6B8 /* GLDTweenBlock.m in Sources */, 3DAE9D5319DBB5EE003692A1 /* GLDTweenTween.m in Sources */, + 117AB29F1B8BECDB00CD92C7 /* GLDTweenChainAction.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Demo/GLDTween/TouchDemo/TouchDemoViewController.m b/Demo/GLDTween/TouchDemo/TouchDemoViewController.m index dcabdb1..9ac4e7b 100644 --- a/Demo/GLDTween/TouchDemo/TouchDemoViewController.m +++ b/Demo/GLDTween/TouchDemo/TouchDemoViewController.m @@ -8,7 +8,7 @@ #import "TouchDemoViewController.h" #import "GLDTween.h" - +#import "GLDTween+Chain.h" @implementation TouchDemoViewController @@ -19,6 +19,9 @@ - (void)viewDidLoad { UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(screenDidToucth:)]; [self.view addGestureRecognizer:gesture]; + UILongPressGestureRecognizer *long_gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(screenDidLongPress:)]; + [self.view addGestureRecognizer:long_gesture]; + self.box.center = CGPointMake(0, 0); CGAffineTransform t = CGAffineTransformMakeTranslation(self.view.frame.size.width*0.5, self.view.frame.size.height*0.5); self.box.transform = t; @@ -50,6 +53,39 @@ - (void)screenDidToucth:(UITapGestureRecognizer*)gesture { @"transform": [NSValue valueWithCGAffineTransform:t]}]; } +- (void)screenDidLongPress:(UILongPressGestureRecognizer*)gesture { + if(gesture.state != UIGestureRecognizerStateBegan){ + return; + } + CGPoint pt = [gesture locationInView:gesture.view]; + float rotation = arc4random() % 360; + float scale = arc4random() % 100 / 50.0 + 0.5; + + CGAffineTransform t1 = CGAffineTransformIdentity; + t1 = CGAffineTransformTranslate(t1, pt.x/2, pt.y/2); + t1 = CGAffineTransformRotate(t1, rotation/2 * M_PI / 180.0); + t1 = CGAffineTransformScale(t1, scale/2, scale/2); + + CGAffineTransform t2 = CGAffineTransformIdentity; + t2 = CGAffineTransformTranslate(t2, pt.x, pt.y); + t2 = CGAffineTransformRotate(t2, rotation * M_PI / 180.0); + t2 = CGAffineTransformScale(t2, scale, scale); + + NSString* transition = [GLDTween easingNames][[self.picker selectedRowInComponent:0]]; + + GLDTween.get(self.box) + .remove() + .to(@{@"duration": @0.4, + @"easing": transition, + @"transform": [NSValue valueWithCGAffineTransform:t1]}) + .wait(0.2) + .to(@{@"duration": @0.4, + @"easing": transition, + @"transform": [NSValue valueWithCGAffineTransform:t2]}) + .call(^(){ + NSLog(@"completed!"); + }); +} - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { } diff --git a/GLDTween/GLDTween+Chain.h b/GLDTween/GLDTween+Chain.h new file mode 100644 index 0000000..c8358d0 --- /dev/null +++ b/GLDTween/GLDTween+Chain.h @@ -0,0 +1,16 @@ +// +// GLDTween+Chain.h +// GLDTween +// +// Created by Ryo Miyake on 2015/08/25. +// Copyright (c) 2014 THE GUILD. All rights reserved. +// + +#import "GLDTween.h" +#import "GLDTweenChain.h" + +@interface GLDTween (Chain) + ++ (GLDTweenChain *(^)(NSObject *target))get; + +@end diff --git a/GLDTween/GLDTween+Chain.m b/GLDTween/GLDTween+Chain.m new file mode 100644 index 0000000..97aad46 --- /dev/null +++ b/GLDTween/GLDTween+Chain.m @@ -0,0 +1,20 @@ +// +// GLDTween+Chain.m +// GLDTween +// +// Created by Ryo Miyake on 2015/08/25. +// Copyright (c) 2014 THE GUILD. All rights reserved. +// + +#import "GLDTween+Chain.h" + +@implementation GLDTween (Chain) + ++ (GLDTweenChain *(^)(NSObject *target))get +{ + return ^GLDTweenChain *(NSObject *target){ + return [GLDTweenChain get:target]; + }; +} + +@end diff --git a/GLDTween/GLDTweenChain.h b/GLDTween/GLDTweenChain.h new file mode 100644 index 0000000..88e13b9 --- /dev/null +++ b/GLDTween/GLDTweenChain.h @@ -0,0 +1,52 @@ +// +// GLDTweenChain.h +// GLDTween +// +// Created by Ryo Miyake on 2015/08/25. +// Copyright (c) 2014 THE GUILD. All rights reserved. +// + +#import + +@interface GLDTweenChain : NSObject + ++ (GLDTweenChain *)get:(NSObject *)target; + +- (GLDTweenChain *)set:(NSDictionary *)params; +- (GLDTweenChain *)to:(NSDictionary *)params; +- (GLDTweenChain *)wait:(NSTimeInterval)delay; +- (GLDTweenChain *)call:(void(^)(void))block; + ++ (void)remove:(NSObject *)target; ++ (void)remove:(NSObject *)target props:(NSArray *)props; ++ (void)removeAllTweens; + ++ (void)pause:(NSObject *)target; ++ (void)pauseAllTweens; + ++ (void)resume:(NSObject *)target; ++ (void)resumeAllTweens; + +@end + +@interface GLDTweenChain(Blocks) + ++ (GLDTweenChain *(^)(NSObject *target))get; + +- (GLDTweenChain *(^)(NSDictionary *params))set; +- (GLDTweenChain *(^)(NSDictionary *params))to; +- (GLDTweenChain *(^)(NSTimeInterval delay))wait; +- (GLDTweenChain *(^)(void(^block)(void)))call; +- (GLDTweenChain *(^)())remove; + ++ (void(^)(NSObject *target))remove; ++ (void(^)(NSObject *target, NSArray *props))removeProps; ++ (void(^)(void))removeAll; + ++ (void(^)(NSObject *target))pause; ++ (void(^)(void))pauseAll; + ++ (void(^)(NSObject *target))resume; ++ (void(^)(void))resumeAll; + +@end diff --git a/GLDTween/GLDTweenChain.m b/GLDTween/GLDTweenChain.m new file mode 100644 index 0000000..9ddd488 --- /dev/null +++ b/GLDTween/GLDTweenChain.m @@ -0,0 +1,372 @@ +// +// GLDTweenChain.m +// GLDTween +// +// Created by Ryo Miyake on 2015/08/25. +// Copyright (c) 2014 THE GUILD. All rights reserved. +// + +#import "GLDTweenChain.h" +#import "GLDTweenChainAction.h" + +@interface GLDTweenChain() +@property (strong, nonatomic) NSObject *target; +@property (strong, nonatomic) NSMutableArray *actionList; +@property (strong, nonatomic) GLDTweenChainAction *currentAction; +@end + +@implementation GLDTweenChain + +@synthesize currentAction = _currentAction; + +static NSMutableArray *all_chains = nil; + +- (id)init:(NSObject *)target +{ + if(self = [self init]){ + _target = target; + _actionList = NSMutableArray.array; + + @synchronized (all_chains) { + [all_chains addObject:self]; + } + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0), dispatch_get_main_queue(), ^{ + [self execute]; + }); + } + return self; +} + ++ (GLDTweenChain*)get:(NSObject *)target +{ + if(!all_chains){ + all_chains = NSMutableArray.array; + } + @synchronized (all_chains){ + for(GLDTweenChain *chain in all_chains){ + if([chain.target isEqual:target]){ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0), dispatch_get_main_queue(), ^{ + [chain resume]; + }); + return chain; + } + } + } + return [[self alloc] init:target]; +} + +- (void)deinit +{ + @synchronized (all_chains){ + [all_chains removeObject:self]; + } +} + +- (void)addAction:(id)action +{ + @synchronized (self){ + [_actionList addObject:action]; + } +} + +- (GLDTweenChainAction*)getNextAction +{ + @synchronized (self){ + id action = [_actionList firstObject]; + if(action) + [_actionList removeObjectAtIndex:0]; + return action; + } +} + +- (void)setCurrentAction:(GLDTweenChainAction *)currentAction +{ + @synchronized (self){ + _currentAction = currentAction; + } +} + +- (GLDTweenChainAction *)currentAction +{ + @synchronized (self){ + return _currentAction; + } +} + +- (void)execute +{ + self.currentAction = nil; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + GLDTweenChainAction *action = [self getNextAction]; + if(action){ + [action executeWithCompleted:^{ + [self execute]; + }]; + self.currentAction = action; + }else{ + [self deinit]; + } + }); +} + +- (GLDTweenChain *)set:(NSDictionary *)params +{ + NSMutableDictionary *params2 = [params mutableCopy]; + [params2 setObject:@0 forKey:@"duration"]; + [self addAction:[[GLDTweenChainActionAdd alloc] initWithTarget:_target params:params2]]; + return self; +} + +- (GLDTweenChain*)to:(NSDictionary *)params +{ + [self addAction:[[GLDTweenChainActionAdd alloc] initWithTarget:_target params:params]]; + return self; +} + +- (GLDTweenChain*)wait:(NSTimeInterval)delay +{ + [self addAction:[[GLDTweenChainActionWait alloc] initWithDelay:delay]]; + return self; +} + +- (GLDTweenChain*)call:(void(^)(void))block +{ + [self addAction:[[GLDTweenChainActionCall alloc] initWithBlock:block]]; + return self; +} + +- (void)_remove +{ + @synchronized (self){ + for(GLDTweenChainAction *action in _actionList){ + [action cancel]; + } + if(_currentAction) + [_currentAction cancel]; + _currentAction = nil; + [_actionList removeAllObjects]; + } + [self deinit]; +} + +- (void)removeProps:(NSArray *)props +{ + @synchronized (self){ + for(GLDTweenChainAction *action in _actionList){ + [action removeProps:props]; + } + if(_currentAction) + [_currentAction removeProps:props]; + } + [self deinit]; +} + +- (void)pause +{ + @synchronized (self){ + for(GLDTweenChainAction *action in _actionList){ + [action pause]; + } + if(_currentAction){ + [_currentAction pause]; + } + } +} + +- (void)resume +{ + @synchronized (self){ + for(GLDTweenChainAction *action in _actionList){ + [action resume]; + } + if(_currentAction) + [_currentAction resume]; + } +} + ++ (void)allChainsFilter:(BOOL(^)(GLDTweenChain *chain))filter + exec:(BOOL(^)(GLDTweenChain *chain))exec +{ + if(!all_chains) + return; + @synchronized (all_chains){ + for(GLDTweenChain *chain in all_chains){ + if(filter(chain)){ + if(!exec(chain)){ + break; + } + } + } + } +} + ++ (void)remove:(NSObject *)target +{ + [self allChainsFilter:^BOOL(GLDTweenChain *chain) { + return [chain.target isEqual:target]; + } + exec:^BOOL(GLDTweenChain *chain) { + [chain _remove]; + return YES; + }]; +} + ++ (void)remove:(NSObject *)target props:(NSArray *)props +{ + [self allChainsFilter:^BOOL(GLDTweenChain *chain) { + return [chain.target isEqual:target]; + } + exec:^BOOL(GLDTweenChain *chain) { + [chain _remove]; + return YES; + }]; +} + ++ (void)removeAllTweens +{ + [self allChainsFilter:^BOOL(GLDTweenChain *chain) { + return YES; + } + exec:^BOOL(GLDTweenChain *chain) { + [chain _remove]; + return YES; + }]; +} + ++ (void)pause:(NSObject *)target +{ + [self allChainsFilter:^BOOL(GLDTweenChain *chain) { + return [chain.target isEqual:target]; + } + exec:^BOOL(GLDTweenChain *chain) { + [chain pause]; + return YES; + }]; +} + ++ (void)pauseAllTweens +{ + [self allChainsFilter:^BOOL(GLDTweenChain *chain) { + return YES; + } + exec:^BOOL(GLDTweenChain *chain) { + [chain pause]; + return YES; + }]; +} + ++ (void)resume:(NSObject *)target +{ + [self allChainsFilter:^BOOL(GLDTweenChain *chain) { + return [chain.target isEqual:target]; + } + exec:^BOOL(GLDTweenChain *chain) { + [chain resume]; + return YES; + }]; +} + ++ (void)resumeAllTweens +{ + [self allChainsFilter:^BOOL(GLDTweenChain *chain) { + return YES; + } + exec:^BOOL(GLDTweenChain *chain) { + [chain resume]; + return YES; + }]; +} + +@end + + +@implementation GLDTweenChain(Blocks) + ++ (GLDTweenChain*(^)(NSObject *target))get +{ + return ^GLDTweenChain *(NSObject *target){ + return [self get:target]; + }; +} + +- (GLDTweenChain *(^)(NSDictionary *params))set +{ + return ^GLDTweenChain *(NSDictionary *params){ + return [self set:params]; + }; +} + +- (GLDTweenChain *(^)(NSDictionary *params))to +{ + return ^GLDTweenChain *(NSDictionary *params){ + return [self to:params]; + }; +} + +- (GLDTweenChain *(^)(NSTimeInterval delay))wait +{ + return ^GLDTweenChain *(NSTimeInterval delay){ + return [self wait:delay]; + }; +} + +- (GLDTweenChain *(^)(void(^block)(void)))call +{ + return ^GLDTweenChain *(void(^block)(void) ){ + return [self call:block]; + }; +} + +- (GLDTweenChain *(^)())remove +{ + return ^GLDTweenChain *(){ + [self _remove]; + return self; + }; +} + ++ (void(^)(NSObject *target))remove +{ + return ^(NSObject *target){ + [self remove:target]; + }; +} + ++ (void(^)(NSObject *target, NSArray *props))removeProps +{ + return ^(NSObject *target, NSArray *props){ + [self remove:target props:props]; + }; +} + ++ (void(^)(void))removeAll +{ + [self removeAllTweens]; + return ^{}; +} + ++ (void(^)(NSObject *target))pause +{ + return ^(NSObject *target){ + [self remove:target]; + }; +} ++ (void(^)(void))pauseAll +{ + [self pauseAllTweens]; + return ^{}; +} + ++ (void(^)(NSObject *target))resume +{ + return ^(NSObject *target){ + [self remove:target]; + }; +} ++ (void(^)(void))resumeAll +{ + [self resumeAllTweens]; + return ^{}; +} + +@end diff --git a/GLDTween/GLDTweenChainAction.h b/GLDTween/GLDTweenChainAction.h new file mode 100644 index 0000000..a72688d --- /dev/null +++ b/GLDTween/GLDTweenChainAction.h @@ -0,0 +1,37 @@ +// +// GLDTweenChainAction.h +// GLDTween +// +// Created by Ryo Miyake on 2015/08/25. +// Copyright (c) 2014 THE GUILD. All rights reserved. +// + +#import + +@interface GLDTweenChainAction : NSObject + +- (void)executeWithCompleted:(void(^)(void))completed; +- (void)cancel; +- (void)pause; +- (void)resume; +- (void)removeProps:(NSArray *)props; + +@end + +@interface GLDTweenChainActionAdd : GLDTweenChainAction + +- (id)initWithTarget:(NSObject*)target params:(NSDictionary*)params; + +@end + +@interface GLDTweenChainActionWait : GLDTweenChainAction + +- (id)initWithDelay:(NSTimeInterval)delay; + +@end + +@interface GLDTweenChainActionCall : GLDTweenChainAction + +- (id)initWithBlock:(void(^)(void))block; + +@end \ No newline at end of file diff --git a/GLDTween/GLDTweenChainAction.m b/GLDTween/GLDTweenChainAction.m new file mode 100644 index 0000000..7d7d86c --- /dev/null +++ b/GLDTween/GLDTweenChainAction.m @@ -0,0 +1,165 @@ +// +// GLDTweenChainAction.m +// GLDTween +// +// Created by Ryo Miyake on 2015/08/25. +// Copyright (c) 2014 THE GUILD. All rights reserved. +// + +#import "GLDTweenChainAction.h" +#import "GLDTween.h" + +@interface GLDTweenChainAction() +@property (atomic, copy) void (^completed)(void); +@property (atomic, assign) BOOL suspended; +@end + +@implementation GLDTweenChainAction + +- (void)executeWithCompleted:(void(^)(void))completed +{ + _completed = completed; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self execute]; + }); +} + +- (void)execute +{ + while (_suspended) { + [NSThread sleepForTimeInterval:.1]; + } +} + +- (void)complete +{ + if(_completed) + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), _completed); +} + +- (void)cancel +{ + _completed = nil; +} + +- (void)pause +{ + _suspended = YES; +} + +- (void)resume +{ + _suspended = NO; +} + +- (void)removeProps:(NSArray *)props +{ +} + +@end + + +@interface GLDTweenChainActionAdd() +@property (strong, nonatomic) NSObject *target; +@property (strong, nonatomic) NSMutableDictionary *params; +@property (strong, nonatomic) GLDTweenBlock *completionBLock; +@end + +@implementation GLDTweenChainActionAdd + +- (id)initWithTarget:(NSObject*)target params:(NSDictionary*)params +{ + if(self = [self init]){ + _target = target; + _params = [params mutableCopy]; + _completionBLock = _params ? _params[GLDTweenParamCompletionBlock] : nil; + } + return self; +} + +- (void)execute +{ + [super execute]; + typeof(self) __weak wself = self; + GLDTweenBlock *block = [[GLDTweenBlock alloc] initWithBlock:^{ + [wself.completionBLock execute]; + [wself complete]; + }]; + _params[GLDTweenParamCompletionBlock] = block; + dispatch_async(dispatch_get_main_queue(), ^{ + [GLDTween addTween:_target withParams:_params]; + }); +} + +- (void)cancel +{ + [super cancel]; + [GLDTween removeTween:_target]; +} + +- (void)pause +{ + [super pause]; + [GLDTween pauseTween:_target]; +} + +- (void)resume +{ + [super resume]; + [GLDTween resumeTween:_target]; +} + +- (void)removeProps:(NSArray *)props +{ + [super removeProps:props]; + [GLDTween removeTween:_target withProps:props]; +} + +@end + +@interface GLDTweenChainActionWait() +@property (assign, nonatomic) NSTimeInterval delay; +@end + +@implementation GLDTweenChainActionWait + +- (id)initWithDelay:(NSTimeInterval)delay +{ + if(self = [self init]){ + _delay = delay; + } + return self; +} + +- (void)execute +{ + [super execute]; + [NSThread sleepForTimeInterval:_delay]; + [self complete]; +} + +@end + +@interface GLDTweenChainActionCall() +@property (nonatomic, copy) void (^block)(void); +@end + +@implementation GLDTweenChainActionCall + +- (id)initWithBlock:(void(^)(void))block +{ + if(self = [self init]){ + _block = block; + } + return self; +} + +- (void)execute +{ + [super execute]; + if(_block) + dispatch_async(dispatch_get_main_queue(), _block); + [self complete]; +} + +@end \ No newline at end of file