Commit a22d1f29 by Dima Bart

Implement thread-safe state changes in BUYOperation. Refactor BUYClient.

parent df7ba142
...@@ -96,7 +96,7 @@ NS_ASSUME_NONNULL_BEGIN ...@@ -96,7 +96,7 @@ NS_ASSUME_NONNULL_BEGIN
/** /**
* Queue where on which all request operation are executed * Queue where on which all request operation are executed
*/ */
@property (nonatomic, strong, nonnull) NSOperationQueue *requestQueue; @property (nonatomic, strong, readonly, nonnull) NSOperationQueue *requestQueue;
/** /**
* Queue where callbacks will be called * Queue where callbacks will be called
......
...@@ -32,12 +32,7 @@ static NSString * const BUYClientJSONMimeType = @"application/json"; ...@@ -32,12 +32,7 @@ static NSString * const BUYClientJSONMimeType = @"application/json";
@interface BUYClient () <NSURLSessionDelegate> @interface BUYClient () <NSURLSessionDelegate>
@property (nonatomic, strong) NSString *shopDomain;
@property (nonatomic, strong) NSString *apiKey;
@property (nonatomic, strong) NSString *appId;
@property (nonatomic, strong) NSURLSession *session; @property (nonatomic, strong) NSURLSession *session;
@property (nonatomic, strong) NSString *merchantId;
@end @end
...@@ -58,15 +53,15 @@ static NSString * const BUYClientJSONMimeType = @"application/json"; ...@@ -58,15 +53,15 @@ static NSString * const BUYClientJSONMimeType = @"application/json";
self = [super init]; self = [super init];
if (self) { if (self) {
self.modelManager = [BUYModelManager modelManager]; _modelManager = [BUYModelManager modelManager];
self.shopDomain = shopDomain; _shopDomain = shopDomain;
self.apiKey = apiKey; _apiKey = apiKey;
self.appId = appId; _appId = appId;
self.applicationName = [[NSBundle mainBundle] infoDictionary][@"CFBundleName"] ?: @""; _applicationName = [[NSBundle mainBundle] infoDictionary][@"CFBundleName"] ?: @"";
self.queue = dispatch_get_main_queue(); _queue = dispatch_get_main_queue();
self.requestQueue = [NSOperationQueue new]; _requestQueue = [NSOperationQueue new];
self.session = [self urlSession]; _session = [self urlSession];
self.pageSize = 25; _pageSize = 25;
} }
return self; return self;
} }
...@@ -219,7 +214,7 @@ static NSString * const BUYClientJSONMimeType = @"application/json"; ...@@ -219,7 +214,7 @@ static NSString * const BUYClientJSONMimeType = @"application/json";
- (void)enableApplePayWithMerchantId:(NSString *)merchantId - (void)enableApplePayWithMerchantId:(NSString *)merchantId
{ {
self.merchantId = merchantId; _merchantId = merchantId;
} }
@end @end
...@@ -10,4 +10,7 @@ ...@@ -10,4 +10,7 @@
@interface BUYOperation : NSOperation @interface BUYOperation : NSOperation
- (void)startExecution;
- (void)finishExecution;
@end @end
...@@ -8,10 +8,15 @@ ...@@ -8,10 +8,15 @@
#import "BUYOperation.h" #import "BUYOperation.h"
typedef NS_ENUM(NSUInteger, BUYOperationState) {
BUYOperationStateExecuting = 1,
BUYOperationStateFinished = 2,
};
@interface BUYOperation () @interface BUYOperation ()
@property (atomic, assign) BOOL isExecuting; @property (nonatomic, assign) BUYOperationState state;
@property (atomic, assign) BOOL isFinished; @property (nonatomic, strong) NSLock *lock;
@end @end
...@@ -23,25 +28,90 @@ ...@@ -23,25 +28,90 @@
{ {
self = [super init]; self = [super init];
if (self) { if (self) {
_lock = [NSLock new];
} }
return self; return self;
} }
#pragma mark - Concurrent -
- (BOOL)isAsynchronous
{
return YES;
}
- (BOOL)isConcurrent
{
return YES;
}
#pragma mark - Accessors -
- (BOOL)isExecuting
{
return self.state == BUYOperationStateExecuting;
}
- (BOOL)isFinished
{
return self.state == BUYOperationStateFinished;
}
#pragma mark - Setters - #pragma mark - Setters -
- (void)setExecuting:(BOOL)executing - (void)setState:(BUYOperationState)state
{ {
[self willChangeValueForKey:@"isExecuting"]; [self.lock lock];
self.isExecuting = executing;
[self didChangeValueForKey:@"isExecuting"]; NSString *oldPath = BUYOperationStateKeyPath(self.state);
NSString *newPath = BUYOperationStateKeyPath(state);
/* ----------------------------------
* We avoid changing state if the new
* state is the same or the operation
* has been cancelled.
*/
if ([oldPath isEqualToString:newPath] || self.isCancelled) {
[self.lock unlock];
return;
}
[self willChangeValueForKey:newPath];
[self willChangeValueForKey:oldPath];
_state = state;
NSLog(@"Setting state");
[self didChangeValueForKey:oldPath];
[self didChangeValueForKey:newPath];
[self.lock unlock];
}
#pragma mark - Start -
- (void)start
{
[self startExecution];
}
#pragma mark - Execution -
- (void)startExecution
{
self.state = BUYOperationStateExecuting;
NSLog(@"Started operation");
}
- (void)finishExecution
{
self.state = BUYOperationStateFinished;
NSLog(@"Finished operation");
} }
- (void)setFinished:(BOOL)finished #pragma mark - State -
static inline NSString * BUYOperationStateKeyPath(BUYOperationState state)
{ {
[self willChangeValueForKey:@"isFinished"]; switch (state) {
self.isFinished = finished; case BUYOperationStateFinished: return @"isFinished";
[self didChangeValueForKey:@"isFinished"]; case BUYOperationStateExecuting: return @"isExecuting";
}
return @"";
} }
@end @end
...@@ -11,14 +11,6 @@ NS_ASSUME_NONNULL_BEGIN ...@@ -11,14 +11,6 @@ NS_ASSUME_NONNULL_BEGIN
@protocol BUYSerializable; @protocol BUYSerializable;
typedef NS_ENUM(NSUInteger, BUYRequestMethod) {
BUYRequestMethodGET,
BUYRequestMethodPOST,
BUYRequestMethodPUT,
BUYRequestMethodPATCH,
BUYRequestMethodDELETE,
};
typedef void (^BUYRequestOperationCompletion)(NSDictionary * _Nullable json, NSURLResponse * _Nullable response, NSError * _Nullable error); typedef void (^BUYRequestOperationCompletion)(NSDictionary * _Nullable json, NSURLResponse * _Nullable response, NSError * _Nullable error);
@interface BUYRequestOperation : BUYOperation @interface BUYRequestOperation : BUYOperation
...@@ -26,6 +18,8 @@ typedef void (^BUYRequestOperationCompletion)(NSDictionary * _Nullable json, NSU ...@@ -26,6 +18,8 @@ typedef void (^BUYRequestOperationCompletion)(NSDictionary * _Nullable json, NSU
@property (strong, nonatomic, readonly, nonnull) NSURLSession *session; @property (strong, nonatomic, readonly, nonnull) NSURLSession *session;
@property (strong, nonatomic, readonly, nonnull) NSURLRequest *originalRequest; @property (strong, nonatomic, readonly, nonnull) NSURLRequest *originalRequest;
+ (instancetype)operationWithSession:(NSURLSession *)session request:(NSURLRequest *)request payload:(id<BUYSerializable> _Nullable)payload completion:(BUYRequestOperationCompletion)completion;
- (instancetype)initWithSession:(NSURLSession *)session request:(NSURLRequest *)request payload:(id<BUYSerializable> _Nullable)payload completion:(BUYRequestOperationCompletion)completion; - (instancetype)initWithSession:(NSURLSession *)session request:(NSURLRequest *)request payload:(id<BUYSerializable> _Nullable)payload completion:(BUYRequestOperationCompletion)completion;
@end @end
......
...@@ -44,6 +44,9 @@ NSString * const kShopifyError = @"shopify"; ...@@ -44,6 +44,9 @@ NSString * const kShopifyError = @"shopify";
@implementation BUYRequestOperation @implementation BUYRequestOperation
#pragma mark - Init - #pragma mark - Init -
+ (instancetype)operationWithSession:(NSURLSession *)session request:(NSURLRequest *)request payload:(id<BUYSerializable>)payload completion:(BUYRequestOperationCompletion)completion {
return [[[self class] alloc] initWithSession:session request:request payload:payload completion:completion];
}
- (instancetype)initWithSession:(NSURLSession *)session request:(NSURLRequest *)request payload:(id<BUYSerializable>)payload completion:(BUYRequestOperationCompletion)completion - (instancetype)initWithSession:(NSURLSession *)session request:(NSURLRequest *)request payload:(id<BUYSerializable>)payload completion:(BUYRequestOperationCompletion)completion
{ {
...@@ -60,34 +63,32 @@ NSString * const kShopifyError = @"shopify"; ...@@ -60,34 +63,32 @@ NSString * const kShopifyError = @"shopify";
- (void)finishWithJSON:(id)JSON response:(NSHTTPURLResponse *)response - (void)finishWithJSON:(id)JSON response:(NSHTTPURLResponse *)response
{ {
[self setExecuting:NO]; [self finishExecution];
self.completion(JSON, response, nil); self.completion(JSON, response, nil);
} }
- (void)finishWithError:(NSError *)error response:(NSHTTPURLResponse *)response - (void)finishWithError:(NSError *)error response:(NSHTTPURLResponse *)response
{ {
[self setExecuting:NO]; [self finishExecution];
self.completion(nil, response, error); self.completion(nil, response, error);
} }
- (void)finishByCancellation - (void)finishByCancellation
{ {
[self setFinished:YES]; [self finishExecution];
[self setExecuting:NO];
} }
#pragma mark - Start - #pragma mark - Start -
- (void)start - (void)startExecution
{ {
[super start];
if (self.isCancelled) { if (self.isCancelled) {
[self finishByCancellation]; [self finishByCancellation];
return; return;
} }
[self setExecuting:YES]; [super startExecution];
NSURLSessionDataTask *task = [self.session dataTaskWithRequest:self.originalRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSURLSessionDataTask *task = [self.session dataTaskWithRequest:self.originalRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (self.isCancelled) { if (self.isCancelled) {
...@@ -114,17 +115,4 @@ NSString * const kShopifyError = @"shopify"; ...@@ -114,17 +115,4 @@ NSString * const kShopifyError = @"shopify";
[task resume]; [task resume];
} }
#pragma mark - BUYRequestMethod -
//static inline NSString * BUYRequestMethodString(BUYRequestMethod method)
//{
// switch (method) {
// case BUYRequestMethodGET: return @"GET";
// case BUYRequestMethodPOST: return @"POST";
// case BUYRequestMethodPATCH: return @"PATCH";
// case BUYRequestMethodPUT: return @"PUT";
// case BUYRequestMethodDELETE: return @"DELETE";
// }
//}
@end @end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment