Merge branch 'master' into experimental-1.0RC1

Conflicts:
	AFNetworking/AFHTTPRequestOperation.h
	AFNetworking/AFHTTPRequestOperation.m
This commit is contained in:
Mattt Thompson 2012-04-24 20:36:43 -07:00
commit 7697140bf9
14 changed files with 73 additions and 123 deletions

View file

@ -125,15 +125,7 @@ extern NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *paramete
[NSURL URLWithString:@"http://example2.com/" relativeToURL:baseURL]; // http://example2.com/ [NSURL URLWithString:@"http://example2.com/" relativeToURL:baseURL]; // http://example2.com/
*/ */
@interface AFHTTPClient : NSObject { @interface AFHTTPClient : NSObject
@private
NSURL *_baseURL;
NSStringEncoding _stringEncoding;
AFHTTPClientParameterEncoding _parameterEncoding;
NSMutableArray *_registeredHTTPOperationClassNames;
NSMutableDictionary *_defaultHeaders;
NSOperationQueue *_operationQueue;
}
///--------------------------------------- ///---------------------------------------
/// @name Accessing HTTP Client Properties /// @name Accessing HTTP Client Properties

View file

@ -579,35 +579,42 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock
completionBlock:(void (^)(NSArray *operations))completionBlock completionBlock:(void (^)(NSArray *operations))completionBlock
{ {
__block dispatch_group_t dispatchGroup = dispatch_group_create();
dispatch_retain(dispatchGroup);
NSBlockOperation *batchedOperation = [NSBlockOperation blockOperationWithBlock:^{ NSBlockOperation *batchedOperation = [NSBlockOperation blockOperationWithBlock:^{
if (completionBlock) { dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_main_queue(), ^{ if (completionBlock) {
completionBlock(operations); completionBlock(operations);
}); }
} });
dispatch_release(dispatchGroup);
}]; }];
[self.operationQueue addOperation:batchedOperation];
NSPredicate *finishedOperationPredicate = [NSPredicate predicateWithFormat:@"isFinished == YES"]; NSPredicate *finishedOperationPredicate = [NSPredicate predicateWithFormat:@"isFinished == YES"];
for (AFHTTPRequestOperation *operation in operations) { for (AFHTTPRequestOperation *operation in operations) {
AFCompletionBlock originalCompletionBlock = [[operation.completionBlock copy] autorelease]; AFCompletionBlock originalCompletionBlock = [[operation.completionBlock copy] autorelease];
operation.completionBlock = ^{ operation.completionBlock = ^{
if (progressBlock) { dispatch_queue_t queue = operation.successCallbackQueue ? operation.successCallbackQueue : dispatch_get_main_queue();
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_group_async(dispatchGroup, queue, ^{
progressBlock([[batchedOperation.dependencies filteredArrayUsingPredicate:finishedOperationPredicate] count], [batchedOperation.dependencies count]); if (originalCompletionBlock) {
}); originalCompletionBlock();
} }
if (originalCompletionBlock) { if (progressBlock) {
originalCompletionBlock(); progressBlock([[operations filteredArrayUsingPredicate:finishedOperationPredicate] count], [operations count]);
} }
dispatch_group_leave(dispatchGroup);
});
}; };
dispatch_group_enter(dispatchGroup);
[batchedOperation addDependency:operation]; [batchedOperation addDependency:operation];
[self enqueueHTTPRequestOperation:operation]; [self enqueueHTTPRequestOperation:operation];
} }
[self.operationQueue addOperation:batchedOperation];
} }
#pragma mark - #pragma mark -
@ -757,7 +764,7 @@ static inline NSString * AFMultipartFormFinalBoundary() {
} }
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileURL]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:fileURL];
[request setCachePolicy:NSURLCacheStorageNotAllowed]; [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
NSURLResponse *response = nil; NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:error]; NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:error];

View file

@ -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. `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 { @interface AFHTTPRequestOperation : AFURLConnectionOperation
@private
NSError *_HTTPError;
dispatch_queue_t _successCallbackQueue;
dispatch_queue_t _failureCallbackQueue;
}
///---------------------------------------------- ///----------------------------------------------
/// @name Getting HTTP URL Connection Information /// @name Getting HTTP URL Connection Information

View file

@ -112,7 +112,7 @@ static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) {
dispatch_release(_failureCallbackQueue); dispatch_release(_failureCallbackQueue);
_failureCallbackQueue = NULL; _failureCallbackQueue = NULL;
} }
[super dealloc]; [super dealloc];
} }
@ -156,6 +156,7 @@ static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) {
if (successCallbackQueue != _successCallbackQueue) { if (successCallbackQueue != _successCallbackQueue) {
if (_successCallbackQueue) { if (_successCallbackQueue) {
dispatch_release(_successCallbackQueue); dispatch_release(_successCallbackQueue);
_successCallbackQueue = NULL;
} }
if (successCallbackQueue) { if (successCallbackQueue) {
@ -169,6 +170,7 @@ static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) {
if (failureCallbackQueue != _failureCallbackQueue) { if (failureCallbackQueue != _failureCallbackQueue) {
if (_failureCallbackQueue) { if (_failureCallbackQueue) {
dispatch_release(_failureCallbackQueue); dispatch_release(_failureCallbackQueue);
_failureCallbackQueue = NULL;
} }
if (failureCallbackQueue) { if (failureCallbackQueue) {

View file

@ -49,15 +49,7 @@
- `image/x-xbitmap` - `image/x-xbitmap`
- `image/x-win-bitmap` - `image/x-win-bitmap`
*/ */
@interface AFImageRequestOperation : AFHTTPRequestOperation { @interface AFImageRequestOperation : AFHTTPRequestOperation
@private
#if __IPHONE_OS_VERSION_MIN_REQUIRED
UIImage *_responseImage;
CGFloat _imageScale;
#elif __MAC_OS_X_VERSION_MIN_REQUIRED
NSImage *_responseImage;
#endif
}
/** /**
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. 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.

View file

@ -79,12 +79,17 @@ static dispatch_queue_t image_request_operation_processing_queue() {
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
if (success) { if (success) {
UIImage *image = responseObject; UIImage *image = responseObject;
if (imageProcessingBlock) { 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) { } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (failure) { if (failure) {
@ -106,12 +111,17 @@ static dispatch_queue_t image_request_operation_processing_queue() {
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
if (success) { if (success) {
NSImage *image = responseObject; NSImage *image = responseObject;
if (imageProcessingBlock) { 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) { } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (failure) { if (failure) {
@ -157,9 +167,7 @@ static dispatch_queue_t image_request_operation_processing_queue() {
return; return;
} }
[self willChangeValueForKey:@"imageScale"];
_imageScale = imageScale; _imageScale = imageScale;
[self didChangeValueForKey:@"imageScale"];
self.responseImage = nil; self.responseImage = nil;
} }

View file

@ -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. @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 { @interface AFJSONRequestOperation : AFHTTPRequestOperation
@private
id _responseJSON;
NSError *_JSONError;
}
///---------------------------- ///----------------------------
/// @name Getting Response Data /// @name Getting Response Data

View file

@ -114,7 +114,7 @@ static dispatch_queue_t json_request_operation_processing_queue() {
}); });
} }
} else { } else {
dispatch_async(json_request_operation_processing_queue(), ^(void) { dispatch_async(json_request_operation_processing_queue(), ^{
id JSON = self.responseJSON; id JSON = self.responseJSON;
if (self.JSONError) { if (self.JSONError) {

View file

@ -32,13 +32,7 @@
- `application/x-plist` - `application/x-plist`
*/ */
@interface AFPropertyListRequestOperation : AFHTTPRequestOperation { @interface AFPropertyListRequestOperation : AFHTTPRequestOperation
@private
id _responsePropertyList;
NSPropertyListFormat _propertyListFormat;
NSPropertyListReadOptions _propertyListReadOptions;
NSError *_propertyListError;
}
///---------------------------- ///----------------------------
/// @name Getting Response Data /// @name Getting Response Data

View file

@ -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. @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 { @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;
}
///------------------------------- ///-------------------------------
/// @name Accessing Run Loop Modes /// @name Accessing Run Loop Modes

View file

@ -91,6 +91,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
@interface AFURLConnectionOperation () @interface AFURLConnectionOperation ()
@property (readwrite, nonatomic, assign) AFOperationState state; @property (readwrite, nonatomic, assign) AFOperationState state;
@property (readwrite, nonatomic, assign, getter = isCancelled) BOOL cancelled;
@property (readwrite, nonatomic, retain) NSRecursiveLock *lock; @property (readwrite, nonatomic, retain) NSRecursiveLock *lock;
@property (readwrite, nonatomic, retain) NSURLConnection *connection; @property (readwrite, nonatomic, retain) NSURLConnection *connection;
@property (readwrite, nonatomic, retain) NSURLRequest *request; @property (readwrite, nonatomic, retain) NSURLRequest *request;
@ -113,6 +114,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
@implementation AFURLConnectionOperation @implementation AFURLConnectionOperation
@synthesize state = _state; @synthesize state = _state;
@synthesize cancelled = _cancelled;
@synthesize connection = _connection; @synthesize connection = _connection;
@synthesize runLoopModes = _runLoopModes; @synthesize runLoopModes = _runLoopModes;
@synthesize request = _request; @synthesize request = _request;
@ -134,18 +136,9 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
+ (void)networkRequestThreadEntryPoint:(id)__unused object { + (void)networkRequestThreadEntryPoint:(id)__unused object {
do { do {
NSAutoreleasePool *exceptionPool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool *runLoopPool = [[NSAutoreleasePool alloc] init];
NSException *caughtException = nil; [[NSRunLoop currentRunLoop] run];
@try { [runLoopPool drain];
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];
} while (YES); } while (YES);
} }
@ -341,10 +334,6 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
return self.state == AFHTTPOperationFinishedState; return self.state == AFHTTPOperationFinishedState;
} }
- (BOOL)isCancelled {
return _cancelled;
}
- (BOOL)isConcurrent { - (BOOL)isConcurrent {
return YES; return YES;
} }

View file

@ -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. 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 { @interface AFXMLRequestOperation : AFHTTPRequestOperation
@private
NSXMLParser *_responseXMLParser;
#if __MAC_OS_X_VERSION_MIN_REQUIRED
NSXMLDocument *_responseXMLDocument;
#endif
NSError *_XMLError;
}
///---------------------------- ///----------------------------
/// @name Getting Response Data /// @name Getting Response Data

View file

@ -28,8 +28,8 @@
@interface AFImageCache : NSCache @interface AFImageCache : NSCache
- (UIImage *)cachedImageForRequest:(NSURLRequest *)request; - (UIImage *)cachedImageForRequest:(NSURLRequest *)request;
- (void)cacheImageData:(NSData *)imageData - (void)cacheImage:(UIImage *)image
forRequest:(NSURLRequest *)request; forRequest:(NSURLRequest *)request;
@end @end
#pragma mark - #pragma mark -
@ -115,21 +115,25 @@ static char kAFImageRequestOperationObjectKey;
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) { if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) {
self.image = responseObject; self.image = responseObject;
self.af_imageRequestOperation = nil;
} }
if (success) { if (success) {
success(operation.request, operation.response, responseObject); 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) { } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) {
self.af_imageRequestOperation = nil;
}
if (failure) { if (failure) {
failure(operation.request, operation.response, error); failure(operation.request, operation.response, error);
} }
self.af_imageRequestOperation = nil;
}]; }];
self.af_imageRequestOperation = requestOperation; self.af_imageRequestOperation = requestOperation;
@ -162,18 +166,15 @@ static inline NSString * AFImageCacheKeyFromURLRequest(NSURLRequest *request) {
break; break;
} }
UIImage *image = [UIImage imageWithData:[self objectForKey:AFImageCacheKeyFromURLRequest(request)]]; return [self objectForKey:AFImageCacheKeyFromURLRequest(request)];
if (image) {
return [UIImage imageWithCGImage:[image CGImage] scale:[[UIScreen mainScreen] scale] orientation:image.imageOrientation];
}
return image;
} }
- (void)cacheImageData:(NSData *)imageData - (void)cacheImage:(UIImage *)image
forRequest:(NSURLRequest *)request forRequest:(NSURLRequest *)request
{ {
[self setObject:[NSPurgeableData dataWithData:imageData] forKey:AFImageCacheKeyFromURLRequest(request)]; if (image && request) {
[self setObject:image forKey:AFImageCacheKeyFromURLRequest(request)];
}
} }
@end @end

View file

@ -50,9 +50,7 @@
} }
- (void)setTweet:(Tweet *)tweet { - (void)setTweet:(Tweet *)tweet {
[self willChangeValueForKey:@"tweet"];
_tweet = tweet; _tweet = tweet;
[self didChangeValueForKey:@"tweet"];
self.textLabel.text = _tweet.user.username; self.textLabel.text = _tweet.user.username;
self.detailTextLabel.text = _tweet.text; self.detailTextLabel.text = _tweet.text;