diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index 8a23490..cdc1666 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -125,15 +125,7 @@ extern NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *paramete [NSURL URLWithString:@"http://example2.com/" relativeToURL:baseURL]; // http://example2.com/ */ -@interface AFHTTPClient : NSObject { -@private - NSURL *_baseURL; - NSStringEncoding _stringEncoding; - AFHTTPClientParameterEncoding _parameterEncoding; - NSMutableArray *_registeredHTTPOperationClassNames; - NSMutableDictionary *_defaultHeaders; - NSOperationQueue *_operationQueue; -} +@interface AFHTTPClient : NSObject ///--------------------------------------- /// @name Accessing HTTP Client Properties diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index d0e6fe1..3b9c751 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -579,35 +579,42 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock completionBlock:(void (^)(NSArray *operations))completionBlock { + __block dispatch_group_t dispatchGroup = dispatch_group_create(); + dispatch_retain(dispatchGroup); NSBlockOperation *batchedOperation = [NSBlockOperation blockOperationWithBlock:^{ - if (completionBlock) { - dispatch_async(dispatch_get_main_queue(), ^{ + dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ + if (completionBlock) { completionBlock(operations); - }); - } + } + }); + dispatch_release(dispatchGroup); }]; - - [self.operationQueue addOperation:batchedOperation]; - + NSPredicate *finishedOperationPredicate = [NSPredicate predicateWithFormat:@"isFinished == YES"]; for (AFHTTPRequestOperation *operation in operations) { AFCompletionBlock originalCompletionBlock = [[operation.completionBlock copy] autorelease]; operation.completionBlock = ^{ - if (progressBlock) { - dispatch_async(dispatch_get_main_queue(), ^{ - progressBlock([[batchedOperation.dependencies filteredArrayUsingPredicate:finishedOperationPredicate] count], [batchedOperation.dependencies count]); - }); - } - - if (originalCompletionBlock) { - originalCompletionBlock(); - } + dispatch_queue_t queue = operation.successCallbackQueue ? operation.successCallbackQueue : dispatch_get_main_queue(); + dispatch_group_async(dispatchGroup, queue, ^{ + if (originalCompletionBlock) { + originalCompletionBlock(); + } + + if (progressBlock) { + progressBlock([[operations filteredArrayUsingPredicate:finishedOperationPredicate] count], [operations count]); + } + + dispatch_group_leave(dispatchGroup); + }); }; + dispatch_group_enter(dispatchGroup); [batchedOperation addDependency:operation]; + [self enqueueHTTPRequestOperation:operation]; } + [self.operationQueue addOperation:batchedOperation]; } #pragma mark - @@ -757,7 +764,7 @@ static inline NSString * AFMultipartFormFinalBoundary() { } NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileURL]; - [request setCachePolicy:NSURLCacheStorageNotAllowed]; + [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData]; NSURLResponse *response = nil; NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:error]; diff --git a/AFNetworking/AFHTTPRequestOperation.h b/AFNetworking/AFHTTPRequestOperation.h index 95260f3..7692def 100644 --- a/AFNetworking/AFHTTPRequestOperation.h +++ b/AFNetworking/AFHTTPRequestOperation.h @@ -31,12 +31,7 @@ extern NSSet * AFContentTypesFromHTTPHeader(NSString *string); /** `AFHTTPRequestOperation` is a subclass of `AFURLConnectionOperation` for requests using the HTTP or HTTPS protocols. It encapsulates the concept of acceptable status codes and content types, which determine the success or failure of a request. */ -@interface AFHTTPRequestOperation : AFURLConnectionOperation { -@private - NSError *_HTTPError; - dispatch_queue_t _successCallbackQueue; - dispatch_queue_t _failureCallbackQueue; -} +@interface AFHTTPRequestOperation : AFURLConnectionOperation ///---------------------------------------------- /// @name Getting HTTP URL Connection Information diff --git a/AFNetworking/AFHTTPRequestOperation.m b/AFNetworking/AFHTTPRequestOperation.m index df3e7ce..3935fd8 100644 --- a/AFNetworking/AFHTTPRequestOperation.m +++ b/AFNetworking/AFHTTPRequestOperation.m @@ -112,7 +112,7 @@ static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) { dispatch_release(_failureCallbackQueue); _failureCallbackQueue = NULL; } - + [super dealloc]; } @@ -156,6 +156,7 @@ static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) { if (successCallbackQueue != _successCallbackQueue) { if (_successCallbackQueue) { dispatch_release(_successCallbackQueue); + _successCallbackQueue = NULL; } if (successCallbackQueue) { @@ -169,6 +170,7 @@ static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) { if (failureCallbackQueue != _failureCallbackQueue) { if (_failureCallbackQueue) { dispatch_release(_failureCallbackQueue); + _failureCallbackQueue = NULL; } if (failureCallbackQueue) { diff --git a/AFNetworking/AFImageRequestOperation.h b/AFNetworking/AFImageRequestOperation.h index 7456d5f..7a7f78a 100644 --- a/AFNetworking/AFImageRequestOperation.h +++ b/AFNetworking/AFImageRequestOperation.h @@ -49,15 +49,7 @@ - `image/x-xbitmap` - `image/x-win-bitmap` */ -@interface AFImageRequestOperation : AFHTTPRequestOperation { -@private -#if __IPHONE_OS_VERSION_MIN_REQUIRED - UIImage *_responseImage; - CGFloat _imageScale; -#elif __MAC_OS_X_VERSION_MIN_REQUIRED - NSImage *_responseImage; -#endif -} +@interface AFImageRequestOperation : AFHTTPRequestOperation /** An image constructed from the response data. If an error occurs during the request, `nil` will be returned, and the `error` property will be set to the error. diff --git a/AFNetworking/AFImageRequestOperation.m b/AFNetworking/AFImageRequestOperation.m index 34a1fd6..3821046 100644 --- a/AFNetworking/AFImageRequestOperation.m +++ b/AFNetworking/AFImageRequestOperation.m @@ -79,12 +79,17 @@ static dispatch_queue_t image_request_operation_processing_queue() { [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { if (success) { UIImage *image = responseObject; - if (imageProcessingBlock) { - image = imageProcessingBlock(image); + dispatch_async(image_request_operation_processing_queue(), ^(void) { + UIImage *processedImage = imageProcessingBlock(image); + + dispatch_async(dispatch_get_main_queue(), ^(void) { + success(operation.request, operation.response, processedImage); + }); + }); + } else { + success(operation.request, operation.response, image); } - - success(operation.request, operation.response, image); } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { if (failure) { @@ -106,12 +111,17 @@ static dispatch_queue_t image_request_operation_processing_queue() { [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { if (success) { NSImage *image = responseObject; - if (imageProcessingBlock) { - image = imageProcessingBlock(image); + dispatch_async(image_request_operation_processing_queue(), ^(void) { + NSImage *processedImage = imageProcessingBlock(image); + + dispatch_async(dispatch_get_main_queue(), ^(void) { + success(operation.request, operation.response, processedImage); + }); + }); + } else { + success(operation.request, operation.response, image); } - - success(operation.request, operation.response, image); } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { if (failure) { @@ -157,9 +167,7 @@ static dispatch_queue_t image_request_operation_processing_queue() { return; } - [self willChangeValueForKey:@"imageScale"]; _imageScale = imageScale; - [self didChangeValueForKey:@"imageScale"]; self.responseImage = nil; } diff --git a/AFNetworking/AFJSONRequestOperation.h b/AFNetworking/AFJSONRequestOperation.h index 7c6a579..a1191f9 100644 --- a/AFNetworking/AFJSONRequestOperation.h +++ b/AFNetworking/AFJSONRequestOperation.h @@ -35,11 +35,7 @@ @warning JSON parsing will automatically use JSONKit, SBJSON, YAJL, or NextiveJSON, if provided. Otherwise, the built-in `NSJSONSerialization` class is used, if available (iOS 5.0 and Mac OS 10.7). If the build target does not either support `NSJSONSerialization` or include a third-party JSON library, a runtime exception will be thrown when attempting to parse a JSON request. */ -@interface AFJSONRequestOperation : AFHTTPRequestOperation { -@private - id _responseJSON; - NSError *_JSONError; -} +@interface AFJSONRequestOperation : AFHTTPRequestOperation ///---------------------------- /// @name Getting Response Data diff --git a/AFNetworking/AFJSONRequestOperation.m b/AFNetworking/AFJSONRequestOperation.m index 451705e..9d40368 100644 --- a/AFNetworking/AFJSONRequestOperation.m +++ b/AFNetworking/AFJSONRequestOperation.m @@ -114,7 +114,7 @@ static dispatch_queue_t json_request_operation_processing_queue() { }); } } else { - dispatch_async(json_request_operation_processing_queue(), ^(void) { + dispatch_async(json_request_operation_processing_queue(), ^{ id JSON = self.responseJSON; if (self.JSONError) { diff --git a/AFNetworking/AFPropertyListRequestOperation.h b/AFNetworking/AFPropertyListRequestOperation.h index 150041c..aa6e471 100644 --- a/AFNetworking/AFPropertyListRequestOperation.h +++ b/AFNetworking/AFPropertyListRequestOperation.h @@ -32,13 +32,7 @@ - `application/x-plist` */ -@interface AFPropertyListRequestOperation : AFHTTPRequestOperation { -@private - id _responsePropertyList; - NSPropertyListFormat _propertyListFormat; - NSPropertyListReadOptions _propertyListReadOptions; - NSError *_propertyListError; -} +@interface AFPropertyListRequestOperation : AFHTTPRequestOperation ///---------------------------- /// @name Getting Response Data diff --git a/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFURLConnectionOperation.h index c9294d3..25a9415 100644 --- a/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFURLConnectionOperation.h @@ -75,24 +75,7 @@ extern NSString * const AFNetworkingOperationDidFinishNotification; @warning Attempting to load a `file://` URL in iOS 4 may result in an `NSInvalidArgumentException`, caused by the connection returning `NSURLResponse` rather than `NSHTTPURLResponse`, which is the behavior as of iOS 5. */ -@interface AFURLConnectionOperation : NSOperation { -@private - unsigned short _state; - BOOL _cancelled; - NSRecursiveLock *_lock; - - NSSet *_runLoopModes; - - NSURLConnection *_connection; - NSURLRequest *_request; - NSHTTPURLResponse *_response; - NSError *_error; - - NSData *_responseData; - NSInteger _totalBytesRead; - NSMutableData *_dataAccumulator; - NSOutputStream *_outputStream; -} +@interface AFURLConnectionOperation : NSOperation ///------------------------------- /// @name Accessing Run Loop Modes diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index a370e0c..b01da2b 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -91,6 +91,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat @interface AFURLConnectionOperation () @property (readwrite, nonatomic, assign) AFOperationState state; +@property (readwrite, nonatomic, assign, getter = isCancelled) BOOL cancelled; @property (readwrite, nonatomic, retain) NSRecursiveLock *lock; @property (readwrite, nonatomic, retain) NSURLConnection *connection; @property (readwrite, nonatomic, retain) NSURLRequest *request; @@ -113,6 +114,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat @implementation AFURLConnectionOperation @synthesize state = _state; +@synthesize cancelled = _cancelled; @synthesize connection = _connection; @synthesize runLoopModes = _runLoopModes; @synthesize request = _request; @@ -134,18 +136,9 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat + (void)networkRequestThreadEntryPoint:(id)__unused object { do { - NSAutoreleasePool *exceptionPool = [[NSAutoreleasePool alloc] init]; - NSException *caughtException = nil; - @try { - NSAutoreleasePool *runLoopPool = [[NSAutoreleasePool alloc] init]; - [[NSRunLoop currentRunLoop] run]; - [runLoopPool drain]; - } - @catch(NSException *e) { caughtException = e; } - if(caughtException) { - NSLog(NSLocalizedString(@"Unhandled exception on %@ networking thread: %@, userInfo: %@", nil), NSStringFromClass([self class]), caughtException, [caughtException userInfo]); - } - [exceptionPool drain]; + NSAutoreleasePool *runLoopPool = [[NSAutoreleasePool alloc] init]; + [[NSRunLoop currentRunLoop] run]; + [runLoopPool drain]; } while (YES); } @@ -341,10 +334,6 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat return self.state == AFHTTPOperationFinishedState; } -- (BOOL)isCancelled { - return _cancelled; -} - - (BOOL)isConcurrent { return YES; } diff --git a/AFNetworking/AFXMLRequestOperation.h b/AFNetworking/AFXMLRequestOperation.h index 7fa919d..0beb677 100644 --- a/AFNetworking/AFXMLRequestOperation.h +++ b/AFNetworking/AFXMLRequestOperation.h @@ -39,14 +39,7 @@ When `AFXMLRequestOperation` is registered with `AFHTTPClient`, the response object in the success callback of `HTTPRequestOperationWithRequest:success:failure:` will be an instance of `NSXMLParser`. On platforms that support `NSXMLDocument`, you have the option to ignore the response object, and simply use the `responseXMLDocument` property of the operation argument of the callback. */ -@interface AFXMLRequestOperation : AFHTTPRequestOperation { -@private - NSXMLParser *_responseXMLParser; -#if __MAC_OS_X_VERSION_MIN_REQUIRED - NSXMLDocument *_responseXMLDocument; -#endif - NSError *_XMLError; -} +@interface AFXMLRequestOperation : AFHTTPRequestOperation ///---------------------------- /// @name Getting Response Data diff --git a/AFNetworking/UIImageView+AFNetworking.m b/AFNetworking/UIImageView+AFNetworking.m index 9f9d190..ac1f708 100644 --- a/AFNetworking/UIImageView+AFNetworking.m +++ b/AFNetworking/UIImageView+AFNetworking.m @@ -28,8 +28,8 @@ @interface AFImageCache : NSCache - (UIImage *)cachedImageForRequest:(NSURLRequest *)request; -- (void)cacheImageData:(NSData *)imageData - forRequest:(NSURLRequest *)request; +- (void)cacheImage:(UIImage *)image + forRequest:(NSURLRequest *)request; @end #pragma mark - @@ -115,21 +115,25 @@ static char kAFImageRequestOperationObjectKey; [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) { self.image = responseObject; + self.af_imageRequestOperation = nil; } if (success) { success(operation.request, operation.response, responseObject); } - [[[self class] af_sharedImageCache] cacheImageData:operation.responseData forRequest:urlRequest]; + [[[self class] af_sharedImageCache] cacheImage:responseObject forRequest:urlRequest]; - self.af_imageRequestOperation = nil; + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) { + self.af_imageRequestOperation = nil; + } + if (failure) { failure(operation.request, operation.response, error); } - self.af_imageRequestOperation = nil; }]; self.af_imageRequestOperation = requestOperation; @@ -162,18 +166,15 @@ static inline NSString * AFImageCacheKeyFromURLRequest(NSURLRequest *request) { break; } - UIImage *image = [UIImage imageWithData:[self objectForKey:AFImageCacheKeyFromURLRequest(request)]]; - if (image) { - return [UIImage imageWithCGImage:[image CGImage] scale:[[UIScreen mainScreen] scale] orientation:image.imageOrientation]; - } - - return image; + return [self objectForKey:AFImageCacheKeyFromURLRequest(request)]; } -- (void)cacheImageData:(NSData *)imageData - forRequest:(NSURLRequest *)request +- (void)cacheImage:(UIImage *)image + forRequest:(NSURLRequest *)request { - [self setObject:[NSPurgeableData dataWithData:imageData] forKey:AFImageCacheKeyFromURLRequest(request)]; + if (image && request) { + [self setObject:image forKey:AFImageCacheKeyFromURLRequest(request)]; + } } @end diff --git a/iOS Example/Classes/Views/TweetTableViewCell.m b/iOS Example/Classes/Views/TweetTableViewCell.m index 6fee1c0..f44c1f9 100644 --- a/iOS Example/Classes/Views/TweetTableViewCell.m +++ b/iOS Example/Classes/Views/TweetTableViewCell.m @@ -50,9 +50,7 @@ } - (void)setTweet:(Tweet *)tweet { - [self willChangeValueForKey:@"tweet"]; _tweet = tweet; - [self didChangeValueForKey:@"tweet"]; self.textLabel.text = _tweet.user.username; self.detailTextLabel.text = _tweet.text;