Commit a22d1f29 by Dima Bart

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

parent df7ba142
......@@ -96,7 +96,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* 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
......
......@@ -32,12 +32,7 @@ static NSString * const BUYClientJSONMimeType = @"application/json";
@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) NSString *merchantId;
@end
......@@ -58,15 +53,15 @@ static NSString * const BUYClientJSONMimeType = @"application/json";
self = [super init];
if (self) {
self.modelManager = [BUYModelManager modelManager];
self.shopDomain = shopDomain;
self.apiKey = apiKey;
self.appId = appId;
self.applicationName = [[NSBundle mainBundle] infoDictionary][@"CFBundleName"] ?: @"";
self.queue = dispatch_get_main_queue();
self.requestQueue = [NSOperationQueue new];
self.session = [self urlSession];
self.pageSize = 25;
_modelManager = [BUYModelManager modelManager];
_shopDomain = shopDomain;
_apiKey = apiKey;
_appId = appId;
_applicationName = [[NSBundle mainBundle] infoDictionary][@"CFBundleName"] ?: @"";
_queue = dispatch_get_main_queue();
_requestQueue = [NSOperationQueue new];
_session = [self urlSession];
_pageSize = 25;
}
return self;
}
......@@ -219,7 +214,7 @@ static NSString * const BUYClientJSONMimeType = @"application/json";
- (void)enableApplePayWithMerchantId:(NSString *)merchantId
{
self.merchantId = merchantId;
_merchantId = merchantId;
}
@end
......@@ -10,4 +10,7 @@
@interface BUYOperation : NSOperation
- (void)startExecution;
- (void)finishExecution;
@end
......@@ -8,10 +8,15 @@
#import "BUYOperation.h"
typedef NS_ENUM(NSUInteger, BUYOperationState) {
BUYOperationStateExecuting = 1,
BUYOperationStateFinished = 2,
};
@interface BUYOperation ()
@property (atomic, assign) BOOL isExecuting;
@property (atomic, assign) BOOL isFinished;
@property (nonatomic, assign) BUYOperationState state;
@property (nonatomic, strong) NSLock *lock;
@end
......@@ -23,25 +28,90 @@
{
self = [super init];
if (self) {
_lock = [NSLock new];
}
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 -
- (void)setExecuting:(BOOL)executing
- (void)setState:(BUYOperationState)state
{
[self.lock lock];
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 willChangeValueForKey:@"isExecuting"];
self.isExecuting = executing;
[self didChangeValueForKey:@"isExecuting"];
[self startExecution];
}
- (void)setFinished:(BOOL)finished
#pragma mark - Execution -
- (void)startExecution
{
[self willChangeValueForKey:@"isFinished"];
self.isFinished = finished;
[self didChangeValueForKey:@"isFinished"];
self.state = BUYOperationStateExecuting;
NSLog(@"Started operation");
}
- (void)finishExecution
{
self.state = BUYOperationStateFinished;
NSLog(@"Finished operation");
}
#pragma mark - State -
static inline NSString * BUYOperationStateKeyPath(BUYOperationState state)
{
switch (state) {
case BUYOperationStateFinished: return @"isFinished";
case BUYOperationStateExecuting: return @"isExecuting";
}
return @"";
}
@end
......@@ -11,14 +11,6 @@ NS_ASSUME_NONNULL_BEGIN
@protocol BUYSerializable;
typedef NS_ENUM(NSUInteger, BUYRequestMethod) {
BUYRequestMethodGET,
BUYRequestMethodPOST,
BUYRequestMethodPUT,
BUYRequestMethodPATCH,
BUYRequestMethodDELETE,
};
typedef void (^BUYRequestOperationCompletion)(NSDictionary * _Nullable json, NSURLResponse * _Nullable response, NSError * _Nullable error);
@interface BUYRequestOperation : BUYOperation
......@@ -26,6 +18,8 @@ typedef void (^BUYRequestOperationCompletion)(NSDictionary * _Nullable json, NSU
@property (strong, nonatomic, readonly, nonnull) NSURLSession *session;
@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;
@end
......
......@@ -44,6 +44,9 @@ NSString * const kShopifyError = @"shopify";
@implementation BUYRequestOperation
#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
{
......@@ -60,34 +63,32 @@ NSString * const kShopifyError = @"shopify";
- (void)finishWithJSON:(id)JSON response:(NSHTTPURLResponse *)response
{
[self setExecuting:NO];
[self finishExecution];
self.completion(JSON, response, nil);
}
- (void)finishWithError:(NSError *)error response:(NSHTTPURLResponse *)response
{
[self setExecuting:NO];
[self finishExecution];
self.completion(nil, response, error);
}
- (void)finishByCancellation
{
[self setFinished:YES];
[self setExecuting:NO];
[self finishExecution];
}
#pragma mark - Start -
- (void)start
- (void)startExecution
{
[super start];
if (self.isCancelled) {
[self finishByCancellation];
return;
}
[self setExecuting:YES];
[super startExecution];
NSURLSessionDataTask *task = [self.session dataTaskWithRequest:self.originalRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (self.isCancelled) {
......@@ -114,17 +115,4 @@ NSString * const kShopifyError = @"shopify";
[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
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