PINDataTaskOperation.m 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. //
  2. // PINDataTaskOperation.m
  3. // Pods
  4. //
  5. // Created by Garrett Moon on 3/12/15.
  6. //
  7. //
  8. #import "PINDataTaskOperation.h"
  9. #import "PINURLSessionManager.h"
  10. typedef NS_ENUM(NSUInteger, PIDataTaskOperationState) {
  11. PIDataTaskOperationStateReady,
  12. PIDataTaskOperationStateExecuting,
  13. PIDataTaskOperationStateFinished,
  14. };
  15. @interface PINDataTaskOperation () <NSURLSessionDelegate>
  16. {
  17. NSRecursiveLock *_lock;;
  18. }
  19. @property (nonatomic, strong, readwrite) NSURLSessionDataTask *dataTask;
  20. @property (nonatomic, assign, readwrite) PIDataTaskOperationState state;
  21. @end
  22. static inline NSString * PIKeyPathFromOperationState(PIDataTaskOperationState state) {
  23. switch (state) {
  24. case PIDataTaskOperationStateReady:
  25. return @"isReady";
  26. case PIDataTaskOperationStateExecuting:
  27. return @"isExecuting";
  28. case PIDataTaskOperationStateFinished:
  29. return @"isFinished";
  30. }
  31. }
  32. @implementation PINDataTaskOperation
  33. - (instancetype)init
  34. {
  35. if (self = [super init]) {
  36. _state = PIDataTaskOperationStateReady;
  37. _lock = [[NSRecursiveLock alloc] init];
  38. }
  39. return self;
  40. }
  41. + (instancetype)dataTaskOperationWithSessionManager:(PINURLSessionManager *)sessionManager
  42. request:(NSURLRequest *)request
  43. completionHandler:(void (^)(NSURLResponse *response, NSError *error))completionHandler
  44. {
  45. PINDataTaskOperation *operation = [[self alloc] init];
  46. operation.dataTask = [sessionManager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, NSError *error) {
  47. completionHandler(response, error);
  48. if (operation.isCancelled == NO) {
  49. [operation finish];
  50. }
  51. }];
  52. return operation;
  53. }
  54. - (void)start
  55. {
  56. [self lock];
  57. if ([self isCancelled]) {
  58. [self cancelTask];
  59. } else if ([self isReady]) {
  60. self.state = PIDataTaskOperationStateExecuting;
  61. [self.dataTask resume];
  62. }
  63. [self unlock];
  64. }
  65. - (void)cancel
  66. {
  67. [self lock];
  68. if (![self isFinished] && ![self isCancelled]) {
  69. [super cancel];
  70. if ([self isExecuting]) {
  71. [self cancelTask];
  72. }
  73. }
  74. [self unlock];
  75. }
  76. - (BOOL)isConcurrent
  77. {
  78. return YES;
  79. }
  80. - (BOOL)isExecuting
  81. {
  82. return self.state == PIDataTaskOperationStateExecuting;
  83. }
  84. - (BOOL)isFinished
  85. {
  86. return self.state == PIDataTaskOperationStateFinished;
  87. }
  88. - (void)finish
  89. {
  90. self.state = PIDataTaskOperationStateFinished;
  91. }
  92. - (void)cancelTask
  93. {
  94. [self lock];
  95. if (![self isFinished]) {
  96. if (self.dataTask) {
  97. [self.dataTask cancel];
  98. }
  99. [self finish];
  100. }
  101. [self unlock];
  102. }
  103. - (void)setState:(PIDataTaskOperationState)state
  104. {
  105. [self lock];
  106. NSString *oldStateKey = PIKeyPathFromOperationState(self.state);
  107. NSString *newStateKey = PIKeyPathFromOperationState(state);
  108. [self willChangeValueForKey:newStateKey];
  109. [self willChangeValueForKey:oldStateKey];
  110. _state = state;
  111. [self didChangeValueForKey:oldStateKey];
  112. [self didChangeValueForKey:newStateKey];
  113. [self unlock];
  114. }
  115. - (void)lock
  116. {
  117. [_lock lock];
  118. }
  119. - (void)unlock
  120. {
  121. [_lock unlock];
  122. }
  123. @end