Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
AMAsynchronousOperation
#import "AMAsynchronousOperation.h"
@interface AMAsynchronousOperation ()
@property (nonatomic, assign, readwrite) AMAsynchronousOperationState state;
@end
#ifndef AMAsynchronousOperation_FinishIfCancelled
#define AMAsynchronousOperation_FinishIfCancelled() \
if (self.isCancelled) { \
self.state = AMAsynchronousOperationStateFinished; \
return; \
}
#endif
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, AMAsynchronousOperationState) {
AMAsynchronousOperationStateReady,
AMAsynchronousOperationStateExecuting,
AMAsynchronousOperationStateFinished,
};
@interface AMAsynchronousOperation : NSOperation
#pragma mark Subclasses
@property (nonatomic, assign, readonly) AMAsynchronousOperationState state;
@end
#import "AMAsynchronousOperation.h"
#import "AMAsynchronousOperation+Private.h"
@implementation AMAsynchronousOperation
- (instancetype)init
{
self = [super init];
if (self) {
_state = AMAsynchronousOperationStateReady;
}
return self;
}
- (BOOL)isAsynchronous
{
return YES;
}
- (BOOL)isReady
{
return super.isReady && AMAsynchronousOperationStateReady == self.state;
}
- (BOOL)isExecuting
{
return AMAsynchronousOperationStateExecuting == self.state;
}
- (BOOL)isFinished
{
return AMAsynchronousOperationStateFinished == self.state;
}
- (void)start
{
if (self.isCancelled) {
self.state = AMAsynchronousOperationStateFinished;
} else {
self.state = AMAsynchronousOperationStateReady;
[self main];
}
}
- (NSString *)keyForState:(AMAsynchronousOperationState)state
{
switch (state) {
case AMAsynchronousOperationStateReady:
return @"isReady";
case AMAsynchronousOperationStateExecuting:
return @"isExecuting";
case AMAsynchronousOperationStateFinished:
return @"isFinished";
}
}
- (void)setState:(AMAsynchronousOperationState)newState
{
if (_state == newState) {
return;
}
AMAsynchronousOperationState oldState = _state;
[self willChangeValueForKey:[self keyForState:oldState]];
[self willChangeValueForKey:[self keyForState:newState]];
[self willChangeValueForKey:@"state"];
_state = newState;
[self didChangeValueForKey:@"state"];
[self didChangeValueForKey:[self keyForState:oldState]];
[self didChangeValueForKey:[self keyForState:newState]];
}
- (void)main
{
AMAsynchronousOperation_FinishIfCancelled();
self.state = AMAsynchronousOperationStateExecuting;
}
@end
@kielgillard

This comment has been minimized.

Copy link

kielgillard commented Jan 1, 2020

Nice. There's a bug in isReady, though. If you're using dependencies, calling super.isReady will return false until all dependencies are completed. So the isReady implementation should probably be something like: return super.isReady && AMAsynchronousOperationStateReady == self.state;

@amrox

This comment has been minimized.

Copy link
Owner Author

amrox commented Jan 2, 2020

@kielgillard thanks for pointing that out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.