From 248c1e5e78d19bb84c8d6f0455e72bef344e0181 Mon Sep 17 00:00:00 2001 From: Carmi Grushko Date: Thu, 1 Nov 2012 18:45:52 +0200 Subject: [PATCH] 1. `RQOperation` remember their progress in properties (uploadBytesTotal, uploadBytesDone, etc.) 2. `RequestQueue` now has OnCompletion handler, which is fired when the queue is empty. --- RequestQueue/RequestQueue.h | 10 ++++++++++ RequestQueue/RequestQueue.m | 35 ++++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/RequestQueue/RequestQueue.h b/RequestQueue/RequestQueue.h index a9fbfbf..c1f57d5 100644 --- a/RequestQueue/RequestQueue.h +++ b/RequestQueue/RequestQueue.h @@ -88,6 +88,10 @@ RequestQueueMode; @property (nonatomic, copy) RQAuthenticationChallengeHandler authenticationChallengeHandler; @property (nonatomic, copy) NSSet *autoRetryErrorCodes; @property (nonatomic, assign) BOOL autoRetry; +@property (nonatomic, assign) NSInteger uploadBytesTotal; +@property (nonatomic, assign) NSInteger uploadBytesDone; +@property (nonatomic, assign) NSInteger downloadBytesTotal; +@property (nonatomic, assign) NSInteger downloadBytesDone; + (RQOperation *)operationWithRequest:(NSURLRequest *)request; - (RQOperation *)initWithRequest:(NSURLRequest *)request; @@ -103,6 +107,7 @@ RequestQueueMode; @property (nonatomic, strong, readonly) NSArray *requests; @property (nonatomic, assign) RequestQueueMode queueMode; @property (nonatomic, assign) BOOL allowDuplicateRequests; +@property (nonatomic, copy) void(^completionHandler)(BOOL success); + (RequestQueue *)mainQueue; @@ -111,4 +116,9 @@ RequestQueueMode; - (void)cancelRequest:(NSURLRequest *)request; - (void)cancelAllRequests; +// Call this method before adding operations to this queue. +// Whenever an operation fails, an internal success flag becomes `NO`. +// This flag is then passed to the `completionHandler` block. +- (void)clearSuccessFlag; + @end diff --git a/RequestQueue/RequestQueue.m b/RequestQueue/RequestQueue.m index c87536d..9321978 100644 --- a/RequestQueue/RequestQueue.m +++ b/RequestQueue/RequestQueue.m @@ -44,6 +44,7 @@ @interface RQOperation () @property (assign, getter = isExecuting) BOOL executing; @property (assign, getter = isFinished) BOOL finished; @property (assign, getter = isCancelled) BOOL cancelled; +@property (assign) BOOL success; @end @@ -117,7 +118,7 @@ - (void)cancel } } -- (void)finish +- (void)finish:(BOOL)success { @synchronized (self) { @@ -127,6 +128,7 @@ - (void)finish [self willChangeValueForKey:@"isFinished"]; _executing = NO; _finished = YES; + _success = success; [self didChangeValueForKey:@"isFinished"]; [self didChangeValueForKey:@"isExecuting"]; } @@ -179,7 +181,7 @@ - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)err } else { - [self finish]; + [self finish:NO]; if (_completionHandler) _completionHandler(_responseReceived, _accumulatedData, error); } } @@ -203,6 +205,8 @@ - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLRespon - (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite { + self.uploadBytesTotal = totalBytesExpectedToWrite; + self.uploadBytesDone = totalBytesWritten; if (_uploadProgressHandler) { float progress = (float)totalBytesWritten / (float)totalBytesExpectedToWrite; @@ -217,18 +221,16 @@ - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data _accumulatedData = [[NSMutableData alloc] initWithCapacity:MAX(0, _responseReceived.expectedContentLength)]; } [_accumulatedData appendData:data]; + self.downloadBytesTotal = MAX(0, _responseReceived.expectedContentLength); + self.downloadBytesDone = [_accumulatedData length]; if (_downloadProgressHandler) { - NSInteger bytesTransferred = [_accumulatedData length]; - NSInteger totalBytes = MAX(0, _responseReceived.expectedContentLength); - _downloadProgressHandler((float)bytesTransferred / (float)totalBytes, bytesTransferred, totalBytes); + _downloadProgressHandler((float)self.downloadBytesDone / (float)self.downloadBytesTotal, self.downloadBytesDone, self.downloadBytesTotal); } } - (void)connectionDidFinishLoading:(NSURLConnection *)_connection { - [self finish]; - NSError *error = nil; if ([_responseReceived respondsToSelector:@selector(statusCode)]) { @@ -243,7 +245,8 @@ - (void)connectionDidFinishLoading:(NSURLConnection *)_connection userInfo:infoDict]; } } - + + [self finish:(error == nil)]; if (_completionHandler) _completionHandler(_responseReceived, _accumulatedData, error); } @@ -257,7 +260,9 @@ @interface RequestQueue () @end -@implementation RequestQueue +@implementation RequestQueue { + BOOL _success; +} @synthesize maxConcurrentRequestCount = _maxConcurrentRequestCount; @synthesize suspended = _suspended; @@ -283,6 +288,7 @@ - (id)init _operations = [[NSMutableArray alloc] init]; _maxConcurrentRequestCount = 2; _allowDuplicateRequests = NO; + [self clearSuccessFlag]; } return self; } @@ -313,6 +319,10 @@ - (void)dequeueOperations [(RQOperation *)[_operations objectAtIndex:i] start]; } } + + if ([_operations count] == 0 && self.completionHandler != nil) { + self.completionHandler(_success); + } } #pragma mark Public methods @@ -394,11 +404,18 @@ - (void)cancelAllRequests } } +- (void)clearSuccessFlag { + _success = YES; +} + - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { RQOperation *operation = object; if (!operation.executing) { + if (!operation.success) { + _success = NO; + } [operation removeObserver:self forKeyPath:@"isExecuting"]; [_operations removeObject:operation]; [self dequeueOperations];