The problem
  • There was a problem that animation effect was added after one click. When clicked continuously, multiple animation effects were executed sequentially through the customized Operation and realized in a queue. However, it was found that each click to play the last animation effect was not completely executed before the animation effect was clicked, which did not meet the requirements.
  • Later, I found that there are two attributes in the custom Operation indicating whether the task is being executed and whether the task is completed, as follows
@property (readonly, getter=isExecuting) BOOL executing;
@property (readonly, getter=isFinished) BOOL finished;
Copy the code

Therefore, setting these two attributes while customizing Operation and giving an identity when completing the task in the current queue indicates that the task is complete, as shown in the following code

  • CustomOperation class
@interface CustomOperation : NSOperation

@end
Copy the code
#import "CustomOperation.h" @interface CustomOperation () @property(nonatomic,readwrite,getter=isExecuting)BOOL executing; / / are said task execution @ property (nonatomic readwrite, getter = isFinished) BOOL finished; @end@implementation CustomOperation @synthesize = _executing; @synthesize finished = _finished; - (void)start { @autoreleasepool { self.executing = YES; if (self.cancelled) { [self done]; return; } // Execute the task __weak Typeof (self) weakSelf = self; Dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)); Dispatch_after (delayTime, dispatch_get_main_queue(), ^{NSLog(@" done "); // Manually close [weakSelf done]; }); } } -(void)done { self.finished = YES; self.executing = NO; } # admin mark -- getter // listen and setExecuting - (void)setExecuting: BOOL executing {[self willChangeValueForKey:@"isExecuting"]; _executing = executing; [self didChangeValueForKey:@"isExecuting"]; } - (BOOL)isExecuting { return _executing; } finished - (void)setFinished: BOOL finished {if (_finished! = finished) { [self willChangeValueForKey:@"isFinished"]; _finished = finished; [self didChangeValueForKey:@"isFinished"]; } } - (BOOL)isFinished { return _finished; } // Return YES to identify concurrent Operation - (BOOL)isAsynchronous {return YES; } @endCopy the code
  • Swift version
class AnimationOperation: Operation { var animationView:AnimationView? Var superView:UIView? Var finishCallBack (()->())? Override var isExecuting: Bool {return operationExecuting} Override var isFinished: Bool { return operationFinished } override var isAsynchronous: Bool {return true} // Listen private var operationFinished:Bool = false {willSet {willChangeValue(forKey: "isFinished") } didSet { didChangeValue(forKey: "isFinished") } } private var operationExecuting:Bool = false { willSet { willChangeValue(forKey: "isExecuting") } didSet { didChangeValue(forKey: "IsExecuting")}} / / each click add animation queue class func addOperationShowAnimationView (animationView: animationView superView: UIView) -> AnimationOperation { let operation = AnimationOperation() operation.animationView = animationView operation.superView  = superView return operation } override func start() { self.operationExecuting = true if isCancelled == true { self.done() return } guard let superView = self.superView, let subView = self.animationView, let callback = self.finishCallBack else { print("superView == nil") return } OperationQueue.main.addOperation {[weak self] in superView.addSubview(subView) subView.finishCallBack = { self? .done() callback() } subView.showAnimation() } } private func done() { self.operationFinished = true self.operationExecuting = false } }Copy the code