Ver código fonte

Porting over changes for 0.3.0 release

Mattt Thompson 14 anos atrás
pai
commit
d87b783814
33 arquivos alterados com 1322 adições e 2394 exclusões
  1. 0 62
      AFNetworking/AFHTTPOperation.h
  2. 0 106
      AFNetworking/AFHTTPOperation.m
  3. 0 73
      AFNetworking/AFImageRequestOperation.h
  4. 0 143
      AFNetworking/AFImageRequestOperation.m
  5. 0 245
      AFNetworking/QHTTPOperation/QHTTPOperation.h
  6. 0 653
      AFNetworking/QHTTPOperation/QHTTPOperation.m
  7. 0 119
      AFNetworking/QHTTPOperation/QRunLoopOperation.h
  8. 0 359
      AFNetworking/QHTTPOperation/QRunLoopOperation.m
  9. 56 0
      Example/AFHTTPRequestOperation.h
  10. 269 0
      Example/AFHTTPRequestOperation.m
  11. 13 13
      Example/AFImageCache.h
  12. 60 0
      Example/AFImageCache.m
  13. 42 0
      Example/AFImageRequestOperation.h
  14. 88 0
      Example/AFImageRequestOperation.m
  15. 14 34
      Example/AFJSONRequestOperation.h
  16. 75 0
      Example/AFJSONRequestOperation.m
  17. 9 10
      Example/AFNetworkActivityIndicatorManager.h
  18. 57 0
      Example/AFNetworkActivityIndicatorManager.m
  19. 49 57
      Example/AFNetworking Example.xcodeproj/project.pbxproj
  20. 327 294
      Example/AFNetworking Example.xcodeproj/project.xcworkspace/xcuserdata/mattt.xcuserdatad/UserInterfaceState.xcuserstate
  21. 16 0
      Example/AFNetworking Example.xcodeproj/xcuserdata/mattt.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist
  22. 20 10
      Example/AFRestClient.h
  23. 64 53
      Example/AFRestClient.m
  24. 0 94
      Example/Classes/AFImageRequest.m
  25. 14 8
      Example/Classes/Controllers/NearbySpotsViewController.m
  26. 1 1
      Example/Classes/Models/Spot.h
  27. 14 10
      Example/Classes/Models/Spot.m
  28. 1 4
      Example/Classes/Views/SpotTableViewCell.h
  29. 0 45
      Example/Classes/Views/SpotTableViewCell.m
  30. 0 0
      Example/UIImage+AFNetworking.h
  31. 0 1
      Example/UIImage+AFNetworking.m
  32. 32 0
      Example/UIImageView+AFNetworking.h
  33. 101 0
      Example/UIImageView+AFNetworking.m

+ 0 - 62
AFNetworking/AFHTTPOperation.h

@@ -1,62 +0,0 @@
-// AFHTTPOperation.h
-//
-// Copyright (c) 2011 Gowalla (http://gowalla.com/)
-// 
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-// 
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#import <Foundation/Foundation.h>
-#import "QHTTPOperation.h"
-#import "AFCallback.h"
-
-extern NSString * const AFHTTPOperationDidStartNotification;
-extern NSString * const AFHTTPOperationDidSucceedNotification;
-extern NSString * const AFHTTPOperationDidFailNotification;
-
-extern NSString * const AFHTTPOperationParsedDataErrorKey;
-
-@class AFHTTPOperationCallback;
-
-@interface AFHTTPOperation : QHTTPOperation {
-@private
-	AFHTTPOperationCallback *_callback;
-}
-
-@property (nonatomic, retain) AFHTTPOperationCallback *callback;
-@property (readonly) NSString *responseString;
-
-+ (id)operationWithRequest:(NSURLRequest *)urlRequest callback:(AFHTTPOperationCallback *)callback;
-- (id)initWithRequest:(NSURLRequest *)urlRequest callback:(AFHTTPOperationCallback *)callback;
-
-@end
-
-#pragma mark - AFHTTPOperationCallback
-
-typedef void (^AFHTTPOperationSuccessBlock)(NSURLRequest *request, NSHTTPURLResponse *response, NSDictionary *data);
-typedef void (^AFHTTPOperationErrorBlock)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error);
-
-@protocol AFHTTPOperationCallback <NSObject>
-@optional
-+ (id)callbackWithSuccess:(AFHTTPOperationSuccessBlock)success;
-+ (id)callbackWithSuccess:(AFHTTPOperationSuccessBlock)success error:(AFHTTPOperationErrorBlock)error;
-@end
-
-@interface AFHTTPOperationCallback : AFCallback <AFHTTPOperationCallback>
-@property (readwrite, nonatomic, copy) AFHTTPOperationSuccessBlock successBlock;
-@property (readwrite, nonatomic, copy) AFHTTPOperationErrorBlock errorBlock;
-@end

+ 0 - 106
AFNetworking/AFHTTPOperation.m

@@ -1,106 +0,0 @@
-// AFHTTPOperation.m
-//
-// Copyright (c) 2011 Gowalla (http://gowalla.com/)
-// 
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-// 
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#import "AFHTTPOperation.h"
-#import "JSONKit.h"
-
-NSString * const AFHTTPOperationDidStartNotification = @"com.alamofire.http-operation.start";
-NSString * const AFHTTPOperationDidSucceedNotification = @"com.alamofire.http-operation.success";
-NSString * const AFHTTPOperationDidFailNotification = @"com.alamofire.http-operation.failure";
-
-NSString * const AFHTTPOperationParsedDataErrorKey = @"com.alamofire.http-operation.error.parsed-data";
-
-@implementation AFHTTPOperation
-@synthesize callback = _callback;
-
-+ (id)operationWithRequest:(NSURLRequest *)urlRequest callback:(AFHTTPOperationCallback *)callback {
-    return [[[self alloc] initWithRequest:urlRequest callback:callback] autorelease];
-}
-
-- (id)initWithRequest:(NSURLRequest *)urlRequest callback:(AFHTTPOperationCallback *)callback {
-    self = [super initWithRequest:urlRequest];
-    if (!self) {
-		return nil;
-    }
-	
-	self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/plain", nil];
-	self.callback = callback;	
-	
-    return self;
-}
-
-- (void)dealloc {
-	[_callback release];
-	[super dealloc];
-}
-
-- (NSString *)responseString {
-    return [[[NSString alloc] initWithData:self.responseBody encoding:NSUTF8StringEncoding] autorelease];
-}
-
-#pragma mark - QRunLoopOperation
-
-- (void)operationDidStart {
-	[super operationDidStart];
-	[[NSNotificationCenter defaultCenter] postNotificationName:AFHTTPOperationDidStartNotification object:self];
-}
-
-- (void)finishWithError:(NSError *)error {
-	[super finishWithError:error];
-    
-    NSDictionary *data = nil;
-    if (self.contentTypeAcceptable) {
-        if ([[self.lastResponse MIMEType] isEqualToString:@"application/json"]) {
-            NSError *jsonError = nil;
-            data = [[JSONDecoder decoder] parseJSONData:self.responseBody error:&jsonError];
-        }
-    }
-    
-    if (self.statusCodeAcceptable) {		
-        [[NSNotificationCenter defaultCenter] postNotificationName:AFHTTPOperationDidSucceedNotification object:self];
-        
-        if(self.callback.successBlock) {
-            self.callback.successBlock(self.lastRequest, self.lastResponse, data);
-        }
-    } else {
-        [[NSNotificationCenter defaultCenter] postNotificationName:AFHTTPOperationDidFailNotification object:self];
-        
-        NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:[error userInfo]];
-        [userInfo setValue:[NSHTTPURLResponse localizedStringForStatusCode:[self.lastResponse statusCode]] forKey:NSLocalizedDescriptionKey];
-        [userInfo setValue:[[self.lastRequest URL] absoluteString] forKey:NSURLErrorFailingURLStringErrorKey];
-        [userInfo setValue:data forKey:AFHTTPOperationParsedDataErrorKey];
-        
-        error = [[[NSError alloc] initWithDomain:NSURLErrorDomain code:[self.lastResponse statusCode] userInfo:userInfo] autorelease];
-        
-        if (self.callback.errorBlock) {
-            self.callback.errorBlock(self.lastRequest, self.lastResponse, error);
-        }
-    }
-}
-
-@end
-
-#pragma mark - AFHTTPOperationCallback
-
-@implementation AFHTTPOperationCallback
-@dynamic successBlock, errorBlock;
-@end

+ 0 - 73
AFNetworking/AFImageRequestOperation.h

@@ -1,73 +0,0 @@
-// AFImageRequestOperation.h
-//
-// Copyright (c) 2011 Gowalla (http://gowalla.com/)
-// 
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-// 
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#import <Foundation/Foundation.h>
-#import <UIKit/UIKit.h>
-#import "QHTTPOperation.h"
-#import "AFCallback.h"
-
-typedef enum {
-    AFImageRequestResize                = 1 << 1,
-    AFImageRequestRoundCorners			= 1 << 2,
-    AFImageCacheProcessedImage          = 1 << 0xA,
-	AFImageRequestDefaultOptions		= AFImageRequestResize,
-} AFImageRequestOptions;
-
-@class AFImageRequestOperationCallback;
-
-@interface AFImageRequestOperation : QHTTPOperation {
-@private
-	AFImageRequestOperationCallback *_callback;
-}
-
-@property (nonatomic, retain) AFImageRequestOperationCallback *callback;
-
-+ (id)operationWithRequest:(NSURLRequest *)urlRequest callback:(AFImageRequestOperationCallback *)callback;
-- (id)initWithRequest:(NSURLRequest *)urlRequest callback:(AFImageRequestOperationCallback *)callback;
-
-@end
-
-#pragma mark - AFHTTPOperationCallback
-
-typedef void (^AFImageRequestOperationSuccessBlock)(UIImage *image);
-typedef void (^AFImageRequestOperationErrorBlock)(NSError *error);
-
-@protocol AFImageRequestOperationCallback <NSObject>
-@optional
-+ (id)callbackWithSuccess:(AFImageRequestOperationSuccessBlock)success;
-+ (id)callbackWithSuccess:(AFImageRequestOperationSuccessBlock)success error:(AFImageRequestOperationErrorBlock)error;
-@end
-
-@interface AFImageRequestOperationCallback : AFCallback <AFImageRequestOperationCallback> {
-@private
-    CGSize _imageSize;
-    AFImageRequestOptions _options;
-}
-
-@property (readwrite, nonatomic, assign) CGSize imageSize;
-@property (readwrite, nonatomic, assign) AFImageRequestOptions options;
-
-@property (readwrite, nonatomic, copy) AFImageRequestOperationSuccessBlock successBlock;
-@property (readwrite, nonatomic, copy) AFImageRequestOperationErrorBlock errorBlock;
-
-+ (id)callbackWithSuccess:(AFImageRequestOperationSuccessBlock)success imageSize:(CGSize)imageSize options:(AFImageRequestOptions)options;
-@end

+ 0 - 143
AFNetworking/AFImageRequestOperation.m

@@ -1,143 +0,0 @@
-// AFImageRequestOperation.m
-//
-// Copyright (c) 2011 Gowalla (http://gowalla.com/)
-// 
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-// 
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#import "AFImageRequestOperation.h"
-
-#import "UIImage+AFNetworking.h"
-
-const CGFloat kAFImageRequestJPEGQuality = 0.8;
-const NSUInteger kAFImageRequestMaximumResponseSize = 8 * 1024 * 1024;
-static inline CGSize kAFImageRequestRoundedCornerRadii(CGSize imageSize) {
-    CGFloat dimension = fmaxf(imageSize.width, imageSize.height) * 0.1;
-    return CGSizeMake(dimension, dimension);
-}
-
-@implementation AFImageRequestOperation
-@synthesize callback = _callback;
-
-+ (id)operationWithRequest:(NSURLRequest *)urlRequest callback:(AFImageRequestOperationCallback *)callback {
-    return [[[self alloc] initWithRequest:urlRequest callback:callback] autorelease];
-}
-
-- (id)initWithRequest:(NSURLRequest *)urlRequest callback:(AFImageRequestOperationCallback *)callback {
-	self = [super initWithRequest:urlRequest];
-	if (!self) {
-		return nil;
-	}
-	
-	self.maximumResponseSize = kAFImageRequestMaximumResponseSize;
-	
-	NSMutableIndexSet *statusCodes = [NSMutableIndexSet indexSetWithIndex:0];
-	[statusCodes addIndexesInRange:NSMakeRange(200, 100)];
-	self.acceptableStatusCodes = statusCodes;
-	self.acceptableContentTypes = [NSSet setWithObjects:@"image/png", @"image/jpeg", @"image/pjpeg", @"image/gif", @"application/x-0", nil];
-	self.callback = callback;
-	
-	if (self.callback) {
-		self.runLoopModes = [NSSet setWithObjects:NSRunLoopCommonModes, NSDefaultRunLoopMode, nil];
-	}
-	
-	return self;
-}
-
-#pragma mark - QHTTPRequestOperation
-
-// QHTTPRequestOperation requires this to return an NSHTTPURLResponse, but in certain circumstances, 
-//  this method would otherwise return an instance of its superclass, NSURLResponse
-- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
-	if([response isKindOfClass:[NSHTTPURLResponse class]]) {
-		[super connection:connection didReceiveResponse:response];
-	} else {
-		[super connection:connection didReceiveResponse:[[[NSHTTPURLResponse alloc] initWithURL:[response URL] MIMEType:[response MIMEType] expectedContentLength:[response expectedContentLength] textEncodingName:[response textEncodingName]] autorelease]];
-	}
-}
-
-#pragma mark - QRunLoopOperation
-
-- (void)finishWithError:(NSError *)error {
-	[super finishWithError:error];
-    
-    if (error) {
-        if (self.callback.errorBlock) {
-			self.callback.errorBlock(error);
-		}
-
-        return;
-    }
-	
-	UIImage *image = nil;    
-	if ([[UIScreen mainScreen] scale] == 2.0) {
-		CGImageRef imageRef = [UIImage imageWithData:self.responseBody].CGImage;
-		image = [UIImage imageWithCGImage:imageRef scale:2.0 orientation:UIImageOrientationUp];
-	} else {
-		image = [UIImage imageWithData:self.responseBody]; 
-	}
-	    
-    BOOL didProcessingOnImage = NO;
-    
-    if ((self.callback.options & AFImageRequestResize) && !(CGSizeEqualToSize(image.size, self.callback.imageSize) || CGSizeEqualToSize(self.callback.imageSize, CGSizeZero))) {
-        image = [UIImage imageByScalingAndCroppingImage:image size:self.callback.imageSize];
-        didProcessingOnImage = YES;
-    }
-	if ((self.callback.options & AFImageRequestRoundCorners)) {
-        image = [UIImage imageByRoundingCornersOfImage:image corners:UIRectCornerAllCorners cornerRadii:kAFImageRequestRoundedCornerRadii(image.size)];
-        didProcessingOnImage = YES;
-    }
-    
-	
-    if (self.callback.successBlock) {
-        self.callback.successBlock(image);
-    }
-    
-    if ((self.callback.options & AFImageCacheProcessedImage) && didProcessingOnImage) {
-        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];			
-        NSData *processedImageData = nil;
-        if ((self.callback.options & AFImageRequestRoundCorners) || [[[[self.lastRequest URL] path] pathExtension] isEqualToString:@"png"]) {
-            processedImageData = UIImagePNGRepresentation(image);
-        } else {
-            processedImageData = UIImageJPEGRepresentation(image, kAFImageRequestJPEGQuality);
-        }
-        NSURLResponse *response = [[[NSURLResponse alloc] initWithURL:[self.lastRequest URL] MIMEType:[self.lastResponse MIMEType] expectedContentLength:[processedImageData length] textEncodingName:[self.lastResponse textEncodingName]] autorelease];
-        NSCachedURLResponse *cachedResponse = [[[NSCachedURLResponse alloc] initWithResponse:response data:processedImageData] autorelease];
-        [[NSURLCache sharedURLCache] storeCachedResponse:cachedResponse forRequest:self.lastRequest];
-        [pool drain];
-    }
-}
-
-@end
-
-#pragma mark - AFHTTPOperationCallback
-
-@implementation AFImageRequestOperationCallback : AFCallback
-@synthesize options = _options;
-@synthesize imageSize = _imageSize;
-@dynamic successBlock, errorBlock;
-
-+ (id)callbackWithSuccess:(AFImageRequestOperationSuccessBlock)success imageSize:(CGSize)imageSize options:(AFImageRequestOptions)options {
-    id callback = [self callbackWithSuccess:success];
-    [callback setImageSize:imageSize];
-    [callback setOptions:options];
-    
-    return callback;
-}
-
-@end

+ 0 - 245
AFNetworking/QHTTPOperation/QHTTPOperation.h

@@ -1,245 +0,0 @@
-/*
-    File:       QHTTPOperation.h
-
-    Contains:   An NSOperation that runs an HTTP request.
-
-    Written by: DTS
-
-    Copyright:  Copyright (c) 2010 Apple Inc. All Rights Reserved.
-
-    Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
-                ("Apple") in consideration of your agreement to the following
-                terms, and your use, installation, modification or
-                redistribution of this Apple software constitutes acceptance of
-                these terms.  If you do not agree with these terms, please do
-                not use, install, modify or redistribute this Apple software.
-
-                In consideration of your agreement to abide by the following
-                terms, and subject to these terms, Apple grants you a personal,
-                non-exclusive license, under Apple's copyrights in this
-                original Apple software (the "Apple Software"), to use,
-                reproduce, modify and redistribute the Apple Software, with or
-                without modifications, in source and/or binary forms; provided
-                that if you redistribute the Apple Software in its entirety and
-                without modifications, you must retain this notice and the
-                following text and disclaimers in all such redistributions of
-                the Apple Software. Neither the name, trademarks, service marks
-                or logos of Apple Inc. may be used to endorse or promote
-                products derived from the Apple Software without specific prior
-                written permission from Apple.  Except as expressly stated in
-                this notice, no other rights or licenses, express or implied,
-                are granted by Apple herein, including but not limited to any
-                patent rights that may be infringed by your derivative works or
-                by other works in which the Apple Software may be incorporated.
-
-                The Apple Software is provided by Apple on an "AS IS" basis. 
-                APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
-                WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
-                MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING
-                THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
-                COMBINATION WITH YOUR PRODUCTS.
-
-                IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT,
-                INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-                TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-                DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY
-                OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
-                OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY
-                OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
-                OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF
-                SUCH DAMAGE.
-
-*/
-
-#import "QRunLoopOperation.h"
-
-/*
-    QHTTPOperation is a general purpose NSOperation that runs an HTTP request. 
-    You initialise it with an HTTP request and then, when you run the operation, 
-    it sends the request and gathers the response.  It is quite a complex 
-    object because it handles a wide variety of edge cases, but it's very 
-    easy to use in simple cases:
-
-    1. create the operation with the URL you want to get
-    
-    op = [[[QHTTPOperation alloc] initWithURL:url] autorelease];
-    
-    2. set up any non-default parameters, for example, set which HTTP 
-       content types are acceptable
-    
-    op.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
-    
-    3. enqueue the operation
-    
-    [queue addOperation:op];
-    
-    4. finally, when the operation is done, use the lastResponse and 
-       error properties to find out how things went
-    
-    As mentioned above, QHTTPOperation is very general purpose.  There are a 
-    large number of configuration and result options available to you.
-    
-    o You can specify a NSURLRequest rather than just a URL.
-    
-    o You can configure the run loop and modes on which the NSURLConnection is 
-      scheduled.
-    
-    o You can specify what HTTP status codes and content types are OK.
-      
-    o You can set an authentication delegate to handle authentication challenges.
-    
-    o You can accumulate responses in memory or in an NSOutputStream. 
-    
-    o For in-memory responses, you can specify a default response size 
-      (used to size the response buffer) and a maximum response size 
-      (to prevent unbounded memory use).
-    
-    o You can get at the last request and the last response, to track 
-      redirects.
-
-    o There are a variety of funky debugging options to simulator errors 
-      and delays.
-      
-    Finally, it's perfectly reasonable to subclass QHTTPOperation to meet you 
-    own specific needs.  Specifically, it's common for the subclass to 
-    override -connection:didReceiveResponse: in order to setup the output 
-    stream based on the specific details of the response.
-*/
-
-@protocol QHTTPOperationAuthenticationDelegate;
-
-@interface QHTTPOperation : QRunLoopOperation /* <NSURLConnectionDelegate> */
-{
-    NSURLRequest *      _request;
-    NSIndexSet *        _acceptableStatusCodes;
-    NSSet *             _acceptableContentTypes;
-    id<QHTTPOperationAuthenticationDelegate>    _authenticationDelegate;
-    NSOutputStream *    _responseOutputStream;
-    NSUInteger          _defaultResponseSize;
-    NSUInteger          _maximumResponseSize;
-    NSURLConnection *   _connection;
-    BOOL                _firstData;
-    NSMutableData *     _dataAccumulator;
-    NSURLRequest *      _lastRequest;
-    NSHTTPURLResponse * _lastResponse;
-    NSData *            _responseBody;
-#if ! defined(NDEBUG)
-    NSError *           _debugError;
-    NSTimeInterval      _debugDelay;
-    NSTimer *           _debugDelayTimer;
-#endif
-}
-
-- (id)initWithRequest:(NSURLRequest *)request;      // designated
-- (id)initWithURL:(NSURL *)url;                     // convenience, calls +[NSURLRequest requestWithURL:]
-
-// Things that are configured by the init method and can't be changed.
-
-@property (copy,   readonly)  NSURLRequest *        request;
-@property (copy,   readonly)  NSURL *               URL;
-
-// Things you can configure before queuing the operation.
-
-// runLoopThread and runLoopModes inherited from QRunLoopOperation
-@property (copy,   readwrite) NSIndexSet *          acceptableStatusCodes;  // default is nil, implying 200..299
-@property (copy,   readwrite) NSSet *               acceptableContentTypes; // default is nil, implying anything is acceptable
-@property (assign, readwrite) id<QHTTPOperationAuthenticationDelegate>  authenticationDelegate;
-
-#if ! defined(NDEBUG)
-@property (copy,   readwrite) NSError *             debugError;             // default is nil
-@property (assign, readwrite) NSTimeInterval        debugDelay;             // default is none
-#endif
-
-// Things you can configure up to the point where you start receiving data. 
-// Typically you would change these in -connection:didReceiveResponse:, but 
-// it is possible to change them up to the point where -connection:didReceiveData: 
-// is called for the first time (that is, you could override -connection:didReceiveData: 
-// and change these before calling super).
-
-// IMPORTANT: If you set a response stream, QHTTPOperation calls the response 
-// stream synchronously.  This is fine for file and memory streams, but it would 
-// not work well for other types of streams (like a bound pair).
-
-@property (retain, readwrite) NSOutputStream *      responseOutputStream;   // defaults to nil, which puts response into responseBody
-@property (assign, readwrite) NSUInteger            defaultResponseSize;    // default is 1 MB, ignored if responseOutputStream is set
-@property (assign, readwrite) NSUInteger            maximumResponseSize;    // default is 4 MB, ignored if responseOutputStream is set
-                                                                            // defaults are 1/4 of the above on embedded
-
-// Things that are only meaningful after a response has been received;
-
-@property (assign, readonly, getter=isStatusCodeAcceptable)  BOOL statusCodeAcceptable;
-@property (assign, readonly, getter=isContentTypeAcceptable) BOOL contentTypeAcceptable;
-
-// Things that are only meaningful after the operation is finished.
-
-// error property inherited from QRunLoopOperation
-@property (copy,   readonly)  NSURLRequest *        lastRequest;       
-@property (copy,   readonly)  NSHTTPURLResponse *   lastResponse;       
-
-@property (copy,   readonly)  NSData *              responseBody;   
-
-@end
-
-@interface QHTTPOperation (NSURLConnectionDelegate)
-
-// QHTTPOperation implements all of these methods, so if you override them 
-// you must consider whether or not to call super.
-//
-// These will be called on the operation's run loop thread.
-
-- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace;
-    // Routes the request to the authentication delegate if it exists, otherwise 
-    // just returns NO.
-    
-- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
-    // Routes the request to the authentication delegate if it exists, otherwise 
-    // just cancels the challenge.
-
-- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response;
-    // Latches the request and response in lastRequest and lastResponse.
-    
-- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
-    // Latches the response in lastResponse.
-    
-- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
-    // If this is the first chunk of data, it decides whether the data is going to be 
-    // routed to memory (responseBody) or a stream (responseOutputStream) and makes the 
-    // appropriate preparations.  For this and subsequent data it then actually shuffles 
-    // the data to its destination.
-    
-- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
-    // Completes the operation with either no error (if the response status code is acceptable) 
-    // or an error (otherwise).
-    
-- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
-    // Completes the operation with the error.
-
-@end
-
-@protocol QHTTPOperationAuthenticationDelegate <NSObject>
-@required
-
-// These are called on the operation's run loop thread and have the same semantics as their 
-// NSURLConnection equivalents.  It's important to realise that there is no 
-// didCancelAuthenticationChallenge callback (because NSURLConnection doesn't issue one to us).  
-// Rather, an authentication delegate is expected to observe the operation and cancel itself 
-// if the operation completes while the challenge is running.
-
-- (BOOL)httpOperation:(QHTTPOperation *)operation canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace;
-- (void)httpOperation:(QHTTPOperation *)operation didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
-
-@end
-
-extern NSString * kQHTTPOperationErrorDomain;
-
-// positive error codes are HTML status codes (when they are not allowed via acceptableStatusCodes)
-//
-// 0 is, of course, not a valid error code
-//
-// negative error codes are errors from the module
-
-enum {
-    kQHTTPOperationErrorResponseTooLarge = -1, 
-    kQHTTPOperationErrorOnOutputStream   = -2, 
-    kQHTTPOperationErrorBadContentType   = -3
-};

+ 0 - 653
AFNetworking/QHTTPOperation/QHTTPOperation.m

@@ -1,653 +0,0 @@
-/*
-    File:       QHTTPOperation.m
-
-    Contains:   An NSOperation that runs an HTTP request.
-
-    Written by: DTS
-
-    Copyright:  Copyright (c) 2010 Apple Inc. All Rights Reserved.
-
-    Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
-                ("Apple") in consideration of your agreement to the following
-                terms, and your use, installation, modification or
-                redistribution of this Apple software constitutes acceptance of
-                these terms.  If you do not agree with these terms, please do
-                not use, install, modify or redistribute this Apple software.
-
-                In consideration of your agreement to abide by the following
-                terms, and subject to these terms, Apple grants you a personal,
-                non-exclusive license, under Apple's copyrights in this
-                original Apple software (the "Apple Software"), to use,
-                reproduce, modify and redistribute the Apple Software, with or
-                without modifications, in source and/or binary forms; provided
-                that if you redistribute the Apple Software in its entirety and
-                without modifications, you must retain this notice and the
-                following text and disclaimers in all such redistributions of
-                the Apple Software. Neither the name, trademarks, service marks
-                or logos of Apple Inc. may be used to endorse or promote
-                products derived from the Apple Software without specific prior
-                written permission from Apple.  Except as expressly stated in
-                this notice, no other rights or licenses, express or implied,
-                are granted by Apple herein, including but not limited to any
-                patent rights that may be infringed by your derivative works or
-                by other works in which the Apple Software may be incorporated.
-
-                The Apple Software is provided by Apple on an "AS IS" basis. 
-                APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
-                WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
-                MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING
-                THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
-                COMBINATION WITH YOUR PRODUCTS.
-
-                IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT,
-                INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-                TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-                DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY
-                OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
-                OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY
-                OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
-                OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF
-                SUCH DAMAGE.
-
-*/
-
-#import "QHTTPOperation.h"
-
-@interface QHTTPOperation ()
-
-// Read/write versions of public properties
-
-@property (copy,   readwrite) NSURLRequest *        lastRequest;
-@property (copy,   readwrite) NSHTTPURLResponse *   lastResponse;
-
-// Internal properties
-
-@property (retain, readwrite) NSURLConnection *     connection;
-@property (assign, readwrite) BOOL                  firstData;
-@property (retain, readwrite) NSMutableData *       dataAccumulator;
-
-#if ! defined(NDEBUG)
-@property (retain, readwrite) NSTimer *             debugDelayTimer;
-#endif
-
-@end
-
-@implementation QHTTPOperation
-
-#pragma mark * Initialise and finalise
-
-- (id)initWithRequest:(NSURLRequest *)request
-    // See comment in header.
-{
-    // any thread
-    assert(request != nil);
-    assert([request URL] != nil);
-    // Because we require an NSHTTPURLResponse, we only support HTTP and HTTPS URLs.
-    assert([[[[request URL] scheme] lowercaseString] isEqual:@"http"] || [[[[request URL] scheme] lowercaseString] isEqual:@"https"]);
-    self = [super init];
-    if (self != nil) {
-        #if TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR
-            static const NSUInteger kPlatformReductionFactor = 4;
-        #else
-            static const NSUInteger kPlatformReductionFactor = 1;
-        #endif
-        self->_request = [request copy];
-        self->_defaultResponseSize = 1 * 1024 * 1024 / kPlatformReductionFactor;
-        self->_maximumResponseSize = 4 * 1024 * 1024 / kPlatformReductionFactor;
-        self->_firstData = YES;
-    }
-    return self;
-}
-
-- (id)initWithURL:(NSURL *)url
-    // See comment in header.
-{
-    assert(url != nil);
-    return [self initWithRequest:[NSURLRequest requestWithURL:url]];
-}
-
-- (void)dealloc
-{
-    #if ! defined(NDEBUG)
-        [self->_debugError release];
-        [self->_debugDelayTimer invalidate];
-        [self->_debugDelayTimer release];
-    #endif
-    // any thread
-    [self->_request release];
-    [self->_acceptableStatusCodes release];
-    [self->_acceptableContentTypes release];
-    [self->_responseOutputStream release];
-    assert(self->_connection == nil);               // should have been shut down by now
-    [self->_dataAccumulator release];
-    [self->_lastRequest release];
-    [self->_lastResponse release];
-    [self->_responseBody release];
-    [super dealloc];
-}
-
-#pragma mark * Properties
-
-// We write our own settings for many properties because we want to bounce 
-// sets that occur in the wrong state.  And, given that we've written the 
-// setter anyway, we also avoid KVO notifications when the value doesn't change.
-
-@synthesize request = _request;
-
-@synthesize authenticationDelegate = _authenticationDelegate;
-
-+ (BOOL)automaticallyNotifiesObserversOfAuthenticationDelegate
-{
-    return NO;
-}
-
-- (id<QHTTPOperationAuthenticationDelegate>)authenticationDelegate
-{
-    return self->_authenticationDelegate;
-}
-
-- (void)setAuthenticationDelegate:(id<QHTTPOperationAuthenticationDelegate>)newValue
-{
-    if (self.state != kQRunLoopOperationStateInited) {
-        assert(NO);
-    } else {
-        if (newValue != self->_authenticationDelegate) {
-            [self willChangeValueForKey:@"authenticationDelegate"];
-            self->_authenticationDelegate = newValue;
-            [self didChangeValueForKey:@"authenticationDelegate"];
-        }
-    }
-}
-
-@synthesize acceptableStatusCodes = _acceptableStatusCodes;
-
-+ (BOOL)automaticallyNotifiesObserversOfAcceptableStatusCodes
-{
-    return NO;
-}
-
-- (NSIndexSet *)acceptableStatusCodes
-{
-    return [[self->_acceptableStatusCodes retain] autorelease];
-}
-
-- (void)setAcceptableStatusCodes:(NSIndexSet *)newValue
-{
-    if (self.state != kQRunLoopOperationStateInited) {
-        assert(NO);
-    } else {
-        if (newValue != self->_acceptableStatusCodes) {
-            [self willChangeValueForKey:@"acceptableStatusCodes"];
-            [self->_acceptableStatusCodes autorelease];
-            self->_acceptableStatusCodes = [newValue copy];
-            [self didChangeValueForKey:@"acceptableStatusCodes"];
-        }
-    }
-}
-
-@synthesize acceptableContentTypes = _acceptableContentTypes;
-
-+ (BOOL)automaticallyNotifiesObserversOfAcceptableContentTypes
-{
-    return NO;
-}
-
-- (NSSet *)acceptableContentTypes
-{
-    return [[self->_acceptableContentTypes retain] autorelease];
-}
-
-- (void)setAcceptableContentTypes:(NSSet *)newValue
-{
-    if (self.state != kQRunLoopOperationStateInited) {
-        assert(NO);
-    } else {
-        if (newValue != self->_acceptableContentTypes) {
-            [self willChangeValueForKey:@"acceptableContentTypes"];
-            [self->_acceptableContentTypes autorelease];
-            self->_acceptableContentTypes = [newValue copy];
-            [self didChangeValueForKey:@"acceptableContentTypes"];
-        }
-    }
-}
-
-@synthesize responseOutputStream = _responseOutputStream;
-
-+ (BOOL)automaticallyNotifiesObserversOfResponseOutputStream
-{
-    return NO;
-}
-
-- (NSOutputStream *)responseOutputStream
-{
-    return [[self->_responseOutputStream retain] autorelease];
-}
-
-- (void)setResponseOutputStream:(NSOutputStream *)newValue
-{
-    if (self.dataAccumulator != nil) {
-        assert(NO);
-    } else {
-        if (newValue != self->_responseOutputStream) {
-            [self willChangeValueForKey:@"responseOutputStream"];
-            [self->_responseOutputStream autorelease];
-            self->_responseOutputStream = [newValue retain];
-            [self didChangeValueForKey:@"responseOutputStream"];
-        }
-    }
-}
-
-@synthesize defaultResponseSize   = _defaultResponseSize;
-
-+ (BOOL)automaticallyNotifiesObserversOfDefaultResponseSize
-{
-    return NO;
-}
-
-- (NSUInteger)defaultResponseSize
-{
-    return self->_defaultResponseSize;
-}
-
-- (void)setDefaultResponseSize:(NSUInteger)newValue
-{
-    if (self.dataAccumulator != nil) {
-        assert(NO);
-    } else {
-        if (newValue != self->_defaultResponseSize) {
-            [self willChangeValueForKey:@"defaultResponseSize"];
-            self->_defaultResponseSize = newValue;
-            [self didChangeValueForKey:@"defaultResponseSize"];
-        }
-    }
-}
-
-@synthesize maximumResponseSize = _maximumResponseSize;
-
-+ (BOOL)automaticallyNotifiesObserversOfMaximumResponseSize
-{
-    return NO;
-}
-
-- (NSUInteger)maximumResponseSize
-{
-    return self->_maximumResponseSize;
-}
-
-- (void)setMaximumResponseSize:(NSUInteger)newValue
-{
-    if (self.dataAccumulator != nil) {
-        assert(NO);
-    } else {
-        if (newValue != self->_maximumResponseSize) {
-            [self willChangeValueForKey:@"maximumResponseSize"];
-            self->_maximumResponseSize = newValue;
-            [self didChangeValueForKey:@"maximumResponseSize"];
-        }
-    }
-}
-
-@synthesize lastRequest     = _lastRequest;
-@synthesize lastResponse    = _lastResponse;
-@synthesize responseBody    = _responseBody;
-
-@synthesize connection      = _connection;
-@synthesize firstData       = _firstData;
-@synthesize dataAccumulator = _dataAccumulator;
-
-- (NSURL *)URL
-{
-    return [self.request URL];
-}
-
-- (BOOL)isStatusCodeAcceptable
-{
-    NSIndexSet *    acceptableStatusCodes;
-    NSInteger       statusCode;
-    
-    assert(self.lastResponse != nil);
-    
-    acceptableStatusCodes = self.acceptableStatusCodes;
-    if (acceptableStatusCodes == nil) {
-        acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)];
-    }
-    assert(acceptableStatusCodes != nil);
-    
-    statusCode = [self.lastResponse statusCode];
-    return (statusCode >= 0) && [acceptableStatusCodes containsIndex: (NSUInteger) statusCode];
-}
-
-- (BOOL)isContentTypeAcceptable
-{
-    NSString *  contentType;
-    
-    assert(self.lastResponse != nil);
-    contentType = [self.lastResponse MIMEType];
-    return (self.acceptableContentTypes == nil) || ((contentType != nil) && [self.acceptableContentTypes containsObject:contentType]);
-}
-
-#pragma mark * Start and finish overrides
-
-- (void)operationDidStart
-    // Called by QRunLoopOperation when the operation starts.  This kicks of an 
-    // asynchronous NSURLConnection.
-{
-    assert(self.isActualRunLoopThread);
-    assert(self.state == kQRunLoopOperationStateExecuting);
-    
-    assert(self.defaultResponseSize > 0);
-    assert(self.maximumResponseSize > 0);
-    assert(self.defaultResponseSize <= self.maximumResponseSize);
-    
-    assert(self.request != nil);
-    
-    // If a debug error is set, apply that error rather than running the connection.
-    
-    #if ! defined(NDEBUG)
-        if (self.debugError != nil) {
-            [self finishWithError:self.debugError];
-            return;
-        }
-    #endif
-
-    // Create a connection that's scheduled in the required run loop modes.
-        
-    assert(self.connection == nil);
-    self.connection = [[[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO] autorelease];
-    assert(self.connection != nil);
-    
-    for (NSString * mode in self.actualRunLoopModes) {
-        [self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:mode];
-    }
-    
-    [self.connection start];
-}
-
-- (void)operationWillFinish
-    // Called by QRunLoopOperation when the operation has finished.  We 
-    // do various bits of tidying up.
-{
-    assert(self.isActualRunLoopThread);
-    assert(self.state == kQRunLoopOperationStateExecuting);
-
-    // It is possible to hit this state of the operation is cancelled while 
-    // the debugDelayTimer is running.  In that case, hey, we'll just accept 
-    // the inevitable and finish rather than trying anything else clever.
-    
-    #if ! defined(NDEBUG)
-        if (self.debugDelayTimer != nil) {
-            [self.debugDelayTimer invalidate];
-            self.debugDelayTimer = nil;
-        }
-    #endif
-
-    [self.connection cancel];
-    self.connection = nil;
-
-    // If we have an output stream, close it at this point.  We might never 
-    // have actually opened this stream but, AFAICT, closing an unopened stream 
-    // doesn't hurt. 
-
-    if (self.responseOutputStream != nil) {
-        [self.responseOutputStream close];
-    }
-}
-
-- (void)finishWithError:(NSError *)error
-    // We override -finishWithError: just so we can handle our debug delay.
-{
-    // If a debug delay was set, don't finish now but rather start the debug delay timer 
-    // and have it do the actual finish.  We clear self.debugDelay so that the next 
-    // time this code runs its doesn't do this again.
-    //
-    // We only do this in the non-cancellation case.  In the cancellation case, we 
-    // just stop immediately.
-    
-    #if ! defined(NDEBUG)
-        if (self.debugDelay > 0.0) {
-            if ( (error != nil) && [[error domain] isEqual:NSCocoaErrorDomain] && ([error code] == NSUserCancelledError) ) {
-                self.debugDelay = 0.0;
-            } else {
-                assert(self.debugDelayTimer == nil);
-                self.debugDelayTimer = [NSTimer timerWithTimeInterval:self.debugDelay target:self selector:@selector(debugDelayTimerDone:) userInfo:error repeats:NO];
-                assert(self.debugDelayTimer != nil);
-                for (NSString * mode in self.actualRunLoopModes) {
-                    [[NSRunLoop currentRunLoop] addTimer:self.debugDelayTimer forMode:mode];
-                }
-                self.debugDelay = 0.0;
-                return;
-            }
-        } 
-    #endif
-
-    [super finishWithError:error];
-}
-
-#if ! defined(NDEBUG)
-
-@synthesize debugError      = _debugError;
-@synthesize debugDelay      = _debugDelay;
-@synthesize debugDelayTimer = _debugDelayTimer;
-
-- (void)debugDelayTimerDone:(NSTimer *)timer
-{
-    NSError *   error;
-    
-    assert(timer == self.debugDelayTimer);
-
-    error = [[[timer userInfo] retain] autorelease];
-    assert( (error == nil) || [error isKindOfClass:[NSError class]] );
-    
-    [self.debugDelayTimer invalidate];
-    self.debugDelayTimer = nil;
-    
-    [self finishWithError:error];
-}
-
-#endif
-
-#pragma mark * NSURLConnection delegate callbacks
-
-- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
-    // See comment in header.
-{
-    BOOL    result;
-    
-    assert(self.isActualRunLoopThread);
-    assert(connection == self.connection);
-    #pragma unused(connection)
-    assert(protectionSpace != nil);
-    #pragma unused(protectionSpace)
-    
-    result = NO;
-    if (self.authenticationDelegate != nil) {
-        result = [self.authenticationDelegate httpOperation:self canAuthenticateAgainstProtectionSpace:protectionSpace];
-    }
-    return result;
-}
-
-- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
-    // See comment in header.
-{
-    assert(self.isActualRunLoopThread);
-    assert(connection == self.connection);
-    #pragma unused(connection)
-    assert(challenge != nil);
-    #pragma unused(challenge)
-    
-    if (self.authenticationDelegate != nil) {
-        [self.authenticationDelegate httpOperation:self didReceiveAuthenticationChallenge:challenge];
-    } else {
-        if ( [challenge previousFailureCount] == 0 ) {
-            [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
-        } else {
-            [[challenge sender] cancelAuthenticationChallenge:challenge];
-        }
-    }
-}
-
-- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response
-    // See comment in header.
-{
-    assert(self.isActualRunLoopThread);
-    assert(connection == self.connection);
-    #pragma unused(connection)
-    assert( (response == nil) || [response isKindOfClass:[NSHTTPURLResponse class]] );
-
-    self.lastRequest  = request;
-    self.lastResponse = (NSHTTPURLResponse *) response;
-    return request;
-}
-
-- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
-    // See comment in header.
-{
-    assert(self.isActualRunLoopThread);
-    assert(connection == self.connection);
-    #pragma unused(connection)
-    assert([response isKindOfClass:[NSHTTPURLResponse class]]);
-
-    self.lastResponse = (NSHTTPURLResponse *) response;
-    
-    // We don't check the status code here because we want to give the client an opportunity 
-    // to get the data of the error message.  Perhaps we /should/ check the content type 
-    // here, but I'm not sure whether that's the right thing to do.
-}
-
-- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
-    // See comment in header.
-{
-    BOOL    success;
-    
-    assert(self.isActualRunLoopThread);
-    assert(connection == self.connection);
-    #pragma unused(connection)
-    assert(data != nil);
-    
-    // If we don't yet have a destination for the data, calculate one.  Note that, even 
-    // if there is an output stream, we don't use it for error responses.
-    
-    success = YES;
-    if (self.firstData) {
-        assert(self.dataAccumulator == nil);
-        
-        if ( (self.responseOutputStream == nil) || ! self.isStatusCodeAcceptable ) {
-            long long   length;
-            
-            assert(self.dataAccumulator == nil);
-            
-            length = [self.lastResponse expectedContentLength];
-            if (length == NSURLResponseUnknownLength) {
-                length = self.defaultResponseSize;
-            }
-            if (length <= (long long) self.maximumResponseSize) {
-                self.dataAccumulator = [NSMutableData dataWithCapacity:(NSUInteger)length];
-            } else {
-                [self finishWithError:[NSError errorWithDomain:kQHTTPOperationErrorDomain code:kQHTTPOperationErrorResponseTooLarge userInfo:nil]];
-                success = NO;
-            }
-        }
-        
-        // If the data is going to an output stream, open it.
-        
-        if (success) {
-            if (self.dataAccumulator == nil) {
-                assert(self.responseOutputStream != nil);
-                [self.responseOutputStream open];
-            }
-        }
-        
-        self.firstData = NO;
-    }
-    
-    // Write the data to its destination.
-
-    if (success) {
-        if (self.dataAccumulator != nil) {
-            if ( ([self.dataAccumulator length] + [data length]) <= self.maximumResponseSize ) {
-                [self.dataAccumulator appendData:data];
-            } else {
-                [self finishWithError:[NSError errorWithDomain:kQHTTPOperationErrorDomain code:kQHTTPOperationErrorResponseTooLarge userInfo:nil]];
-            }
-        } else {
-            NSUInteger      dataOffset;
-            NSUInteger      dataLength;
-            const uint8_t * dataPtr;
-            NSError *       error;
-            NSInteger       bytesWritten;
-
-            assert(self.responseOutputStream != nil);
-
-            dataOffset = 0;
-            dataLength = [data length];
-            dataPtr    = [data bytes];
-            error      = nil;
-            do {
-                if (dataOffset == dataLength) {
-                    break;
-                }
-                bytesWritten = [self.responseOutputStream write:&dataPtr[dataOffset] maxLength:dataLength - dataOffset];
-                if (bytesWritten <= 0) {
-                    error = [self.responseOutputStream streamError];
-                    if (error == nil) {
-                        error = [NSError errorWithDomain:kQHTTPOperationErrorDomain code:kQHTTPOperationErrorOnOutputStream userInfo:nil];
-                    }
-                    break;
-                } else {
-                    dataOffset += bytesWritten;
-                }
-            } while (YES);
-            
-            if (error != nil) {
-                [self finishWithError:error];
-            }
-        }
-    }
-}
-
-- (void)connectionDidFinishLoading:(NSURLConnection *)connection
-    // See comment in header.
-{
-    assert(self.isActualRunLoopThread);
-    assert(connection == self.connection);
-    #pragma unused(connection)
-    
-    assert(self.lastResponse != nil);
-
-    // Swap the data accumulator over to the response data so that we don't trigger a copy.
-    
-    assert(self->_responseBody == nil);
-    self->_responseBody = self->_dataAccumulator;
-    self->_dataAccumulator = nil;
-    
-    // Because we fill out _dataAccumulator lazily, an empty body will leave _dataAccumulator 
-    // set to nil.  That's not what our clients expect, so we fix it here.
-    
-    if (self->_responseBody == nil) {
-        self->_responseBody = [[NSData alloc] init];
-        assert(self->_responseBody != nil);
-    }
-    
-    if ( ! self.isStatusCodeAcceptable ) {
-        [self finishWithError:[NSError errorWithDomain:kQHTTPOperationErrorDomain code:self.lastResponse.statusCode userInfo:nil]];
-    } else if ( ! self.isContentTypeAcceptable ) {
-        [self finishWithError:[NSError errorWithDomain:kQHTTPOperationErrorDomain code:kQHTTPOperationErrorBadContentType userInfo:nil]];
-    } else {
-        [self finishWithError:nil];
-    }
-}
-
-- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
-    // See comment in header.
-{
-    assert(self.isActualRunLoopThread);
-    assert(connection == self.connection);
-    #pragma unused(connection)
-    assert(error != nil);
-
-    [self finishWithError:error];
-}
-
-@end
-
-NSString * kQHTTPOperationErrorDomain = @"kQHTTPOperationErrorDomain";

+ 0 - 119
AFNetworking/QHTTPOperation/QRunLoopOperation.h

@@ -1,119 +0,0 @@
-/*
-    File:       QRunLoopOperation.h
-
-    Contains:   An abstract subclass of NSOperation for async run loop based operations.
-
-    Written by: DTS
-
-    Copyright:  Copyright (c) 2010 Apple Inc. All Rights Reserved.
-
-    Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
-                ("Apple") in consideration of your agreement to the following
-                terms, and your use, installation, modification or
-                redistribution of this Apple software constitutes acceptance of
-                these terms.  If you do not agree with these terms, please do
-                not use, install, modify or redistribute this Apple software.
-
-                In consideration of your agreement to abide by the following
-                terms, and subject to these terms, Apple grants you a personal,
-                non-exclusive license, under Apple's copyrights in this
-                original Apple software (the "Apple Software"), to use,
-                reproduce, modify and redistribute the Apple Software, with or
-                without modifications, in source and/or binary forms; provided
-                that if you redistribute the Apple Software in its entirety and
-                without modifications, you must retain this notice and the
-                following text and disclaimers in all such redistributions of
-                the Apple Software. Neither the name, trademarks, service marks
-                or logos of Apple Inc. may be used to endorse or promote
-                products derived from the Apple Software without specific prior
-                written permission from Apple.  Except as expressly stated in
-                this notice, no other rights or licenses, express or implied,
-                are granted by Apple herein, including but not limited to any
-                patent rights that may be infringed by your derivative works or
-                by other works in which the Apple Software may be incorporated.
-
-                The Apple Software is provided by Apple on an "AS IS" basis. 
-                APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
-                WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
-                MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING
-                THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
-                COMBINATION WITH YOUR PRODUCTS.
-
-                IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT,
-                INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-                TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-                DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY
-                OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
-                OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY
-                OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
-                OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF
-                SUCH DAMAGE.
-
-*/
-
-#import <Foundation/Foundation.h>
-
-enum QRunLoopOperationState {
-    kQRunLoopOperationStateInited, 
-    kQRunLoopOperationStateExecuting, 
-    kQRunLoopOperationStateFinished
-};
-typedef enum QRunLoopOperationState QRunLoopOperationState;
-
-@interface QRunLoopOperation : NSOperation
-{
-    QRunLoopOperationState  _state;
-    NSThread *              _runLoopThread;
-    NSSet *                 _runLoopModes;
-    NSError *               _error;
-}
-
-// Things you can configure before queuing the operation.
-
-// IMPORTANT: Do not change these after queuing the operation; it's very likely that 
-// bad things will happen if you do.
-
-@property (retain, readwrite) NSThread *                runLoopThread;          // default is nil, implying main thread
-@property (copy,   readwrite) NSSet *                   runLoopModes;           // default is nil, implying set containing NSDefaultRunLoopMode
-
-// Things that are only meaningful after the operation is finished.
-
-@property (copy,   readonly ) NSError *                 error;
-
-// Things you can only alter implicitly.
-
-@property (assign, readonly ) QRunLoopOperationState    state;
-@property (retain, readonly ) NSThread *                actualRunLoopThread;    // main thread if runLoopThread is nil, runLoopThread otherwise
-@property (assign, readonly ) BOOL                      isActualRunLoopThread;  // YES if the current thread is the actual run loop thread
-@property (copy,   readonly ) NSSet *                   actualRunLoopModes;     // set containing NSDefaultRunLoopMode if runLoopModes is nil or empty, runLoopModes otherwise
-
-@end
-
-@interface QRunLoopOperation (SubClassSupport)
-
-// Override points
-
-// A subclass will probably need to override -operationDidStart and -operationWillFinish 
-// to set up and tear down its run loop sources, respectively.  These are always called 
-// on the actual run loop thread.
-//
-// Note that -operationWillFinish will be called even if the operation is cancelled. 
-//
-// -operationWillFinish can check the error property to see whether the operation was 
-// successful.  error will be NSCocoaErrorDomain/NSUserCancelledError on cancellation. 
-//
-// -operationDidStart is allowed to call -finishWithError:.
-
-- (void)operationDidStart;
-- (void)operationWillFinish;
-
-// Support methods
-
-// A subclass should call finishWithError: when the operation is complete, passing nil 
-// for no error and an error otherwise.  It must call this on the actual run loop thread. 
-// 
-// Note that this will call -operationWillFinish before returning.
-
-- (void)finishWithError:(NSError *)error;
-
-@end

+ 0 - 359
AFNetworking/QHTTPOperation/QRunLoopOperation.m

@@ -1,359 +0,0 @@
-/*
-    File:       QRunLoopOperation.m
-
-    Contains:   An abstract subclass of NSOperation for async run loop based operations.
-
-    Written by: DTS
-
-    Copyright:  Copyright (c) 2010 Apple Inc. All Rights Reserved.
-
-    Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
-                ("Apple") in consideration of your agreement to the following
-                terms, and your use, installation, modification or
-                redistribution of this Apple software constitutes acceptance of
-                these terms.  If you do not agree with these terms, please do
-                not use, install, modify or redistribute this Apple software.
-
-                In consideration of your agreement to abide by the following
-                terms, and subject to these terms, Apple grants you a personal,
-                non-exclusive license, under Apple's copyrights in this
-                original Apple software (the "Apple Software"), to use,
-                reproduce, modify and redistribute the Apple Software, with or
-                without modifications, in source and/or binary forms; provided
-                that if you redistribute the Apple Software in its entirety and
-                without modifications, you must retain this notice and the
-                following text and disclaimers in all such redistributions of
-                the Apple Software. Neither the name, trademarks, service marks
-                or logos of Apple Inc. may be used to endorse or promote
-                products derived from the Apple Software without specific prior
-                written permission from Apple.  Except as expressly stated in
-                this notice, no other rights or licenses, express or implied,
-                are granted by Apple herein, including but not limited to any
-                patent rights that may be infringed by your derivative works or
-                by other works in which the Apple Software may be incorporated.
-
-                The Apple Software is provided by Apple on an "AS IS" basis. 
-                APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
-                WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
-                MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING
-                THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
-                COMBINATION WITH YOUR PRODUCTS.
-
-                IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT,
-                INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-                TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-                DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY
-                OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
-                OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY
-                OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
-                OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF
-                SUCH DAMAGE.
-
-*/
-
-#import "QRunLoopOperation.h"
-
-/*
-    Theory of Operation
-    -------------------
-    Some critical points:
-    
-     1. By the time we're running on the run loop thread, we know that all further state 
-        transitions happen on the run loop thread.  That's because there are only three 
-        states (inited, executing, and finished) and run loop thread code can only run 
-        in the last two states and the transition from executing to finished is 
-        always done on the run loop thread.
-
-     2. -start can only be called once.  So run loop thread code doesn't have to worry 
-        about racing with -start because, by the time the run loop thread code runs, 
-        -start has already been called.
-        
-     3. -cancel can be called multiple times from any thread.  Run loop thread code 
-        must take a lot of care with do the right thing with cancellation.
-    
-    Some state transitions:
-
-     1. init -> dealloc
-     2. init -> cancel -> dealloc
-XXX  3. init -> cancel -> start -> finish -> dealloc
-     4. init -> cancel -> start -> startOnRunLoopThreadThread -> finish dealloc
-!!!  5. init -> start -> cancel -> startOnRunLoopThreadThread -> finish -> cancelOnRunLoopThreadThread -> dealloc
-XXX  6. init -> start -> cancel -> cancelOnRunLoopThreadThread -> startOnRunLoopThreadThread -> finish -> dealloc
-XXX  7. init -> start -> cancel -> startOnRunLoopThreadThread -> cancelOnRunLoopThreadThread -> finish -> dealloc
-     8. init -> start -> startOnRunLoopThreadThread -> finish -> dealloc
-     9. init -> start -> startOnRunLoopThreadThread -> cancel -> cancelOnRunLoopThreadThread -> finish -> dealloc
-!!! 10. init -> start -> startOnRunLoopThreadThread -> cancel -> finish -> cancelOnRunLoopThreadThread -> dealloc
-    11. init -> start -> startOnRunLoopThreadThread -> finish -> cancel -> dealloc
-
-    Markup:
-        XXX means that the case doesn't happen.
-        !!! means that the case is interesting.
-        
-    Described:
-    
-     1. It's valid to allocate an operation and never run it.
-     2. It's also valid to allocate an operation, cancel it, and yet never run it.
-     3. While it's valid to cancel an operation before it starting it, this case doesn't 
-        happen because -start always bounces to the run loop thread to maintain the invariant 
-        that the executing to finished transition always happens on the run loop thread.
-     4. In this -startOnRunLoopThread detects the cancellation and finishes immediately.
-     5. Because the -cancel can happen on any thread, it's possible for the -cancel 
-        to come in between the -start and the -startOnRunLoop thread.  In this case 
-        -startOnRunLoopThread notices isCancelled and finishes straightaway.  And 
-        -cancelOnRunLoopThread detects that the operation is finished and does nothing.
-     6. This case can never happen because -performSelecton:onThread:xxx 
-        callbacks happen in order, -start is synchronised with -cancel, and -cancel 
-        only schedules if -start has run.
-     7. This case can never happen because -startOnRunLoopThread will finish immediately 
-        if it detects isCancelled (see case 5).
-     8. This is the standard run-to-completion case. 
-     9. This is the standard cancellation case.  -cancelOnRunLoopThread wins the race 
-        with finish, and it detects that the operation is executing and actually cancels. 
-    10. In this case the -cancelOnRunLoopThread loses the race with finish, but that's OK 
-        because -cancelOnRunLoopThread already does nothing if the operation is already 
-        finished.
-    11. Cancellating after finishing still sets isCancelled but has no impact 
-        on the RunLoop thread code.
-*/
-
-@interface QRunLoopOperation ()
-
-// read/write versions of public properties
-
-@property (assign, readwrite) QRunLoopOperationState    state;
-@property (copy,   readwrite) NSError *                 error;          
-
-@end
-
-@implementation QRunLoopOperation
-
-- (id)init
-{
-    self = [super init];
-    if (self != nil) {
-        assert(self->_state == kQRunLoopOperationStateInited);
-    }
-    return self;
-}
-
-- (void)dealloc
-{
-    assert(self->_state != kQRunLoopOperationStateExecuting);
-    [self->_runLoopModes release];
-    [self->_runLoopThread release];
-    [self->_error release];
-    [super dealloc];
-}
-
-#pragma mark * Properties
-
-@synthesize runLoopThread = _runLoopThread;
-@synthesize runLoopModes  = _runLoopModes;
-
-- (NSThread *)actualRunLoopThread
-    // Returns the effective run loop thread, that is, the one set by the user 
-    // or, if that's not set, the main thread.
-{
-    NSThread *  result;
-    
-    result = self.runLoopThread;
-    if (result == nil) {
-        result = [NSThread mainThread];
-    }
-    return result;
-}
-
-- (BOOL)isActualRunLoopThread
-    // Returns YES if the current thread is the actual run loop thread.
-{
-    return [[NSThread currentThread] isEqual:self.actualRunLoopThread];
-}
-
-- (NSSet *)actualRunLoopModes
-{
-    NSSet * result;
-    
-    result = self.runLoopModes;
-    if ( (result == nil) || ([result count] == 0) ) {
-        result = [NSSet setWithObject:NSDefaultRunLoopMode];
-    }
-    return result;
-}
-
-@synthesize error         = _error;
-
-#pragma mark * Core state transitions
-
-- (QRunLoopOperationState)state
-{
-    return self->_state;
-}
-
-- (void)setState:(QRunLoopOperationState)newState
-    // Change the state of the operation, sending the appropriate KVO notifications.
-{
-    // any thread
-
-    @synchronized (self) {
-        QRunLoopOperationState  oldState;
-        
-        // The following check is really important.  The state can only go forward, and there 
-        // should be no redundant changes to the state (that is, newState must never be 
-        // equal to self->_state).
-        
-        assert(newState > self->_state);
-
-        // Transitions from executing to finished must be done on the run loop thread.
-        
-        assert( (newState != kQRunLoopOperationStateFinished) || self.isActualRunLoopThread );
-
-        // inited    + executing -> isExecuting
-        // inited    + finished  -> isFinished
-        // executing + finished  -> isExecuting + isFinished
-
-        oldState = self->_state;
-        if ( (newState == kQRunLoopOperationStateExecuting) || (oldState == kQRunLoopOperationStateExecuting) ) {
-            [self willChangeValueForKey:@"isExecuting"];
-        }
-        if (newState == kQRunLoopOperationStateFinished) {
-            [self willChangeValueForKey:@"isFinished"];
-        }
-        self->_state = newState;
-        if (newState == kQRunLoopOperationStateFinished) {
-            [self didChangeValueForKey:@"isFinished"];
-        }
-        if ( (newState == kQRunLoopOperationStateExecuting) || (oldState == kQRunLoopOperationStateExecuting) ) {
-            [self didChangeValueForKey:@"isExecuting"];
-        }
-    }
-}
-
-- (void)startOnRunLoopThread
-    // Starts the operation.  The actual -start method is very simple, 
-    // deferring all of the work to be done on the run loop thread by this 
-    // method.
-{
-    assert(self.isActualRunLoopThread);
-    assert(self.state == kQRunLoopOperationStateExecuting);
-
-    if ([self isCancelled]) {
-        
-        // We were cancelled before we even got running.  Flip the the finished 
-        // state immediately.
-        
-        [self finishWithError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]];
-    } else {
-        [self operationDidStart];
-    }
-}
-
-- (void)cancelOnRunLoopThread
-    // Cancels the operation.
-{
-    assert(self.isActualRunLoopThread);
-
-    // We know that a) state was kQRunLoopOperationStateExecuting when we were 
-    // scheduled (that's enforced by -cancel), and b) the state can't go 
-    // backwards (that's enforced by -setState), so we know the state must 
-    // either be kQRunLoopOperationStateExecuting or kQRunLoopOperationStateFinished. 
-    // We also know that the transition from executing to finished always 
-    // happens on the run loop thread.  Thus, we don't need to lock here.  
-    // We can look at state and, if we're executing, trigger a cancellation.
-    
-    if (self.state == kQRunLoopOperationStateExecuting) {
-        [self finishWithError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]];
-    }
-}
-
-- (void)finishWithError:(NSError *)error
-{
-    assert(self.isActualRunLoopThread);
-    // error may be nil
-
-    if (self.error == nil) {
-        self.error = error;
-    }
-    [self operationWillFinish];
-    self.state = kQRunLoopOperationStateFinished;
-}
-
-#pragma mark * Subclass override points
-
-- (void)operationDidStart
-{
-    assert(self.isActualRunLoopThread);
-}
-
-- (void)operationWillFinish
-{
-    assert(self.isActualRunLoopThread);
-}
-
-#pragma mark * Overrides
-
-- (BOOL)isConcurrent
-{
-    // any thread
-    return YES;
-}
-
-- (BOOL)isExecuting
-{
-    // any thread
-    return self.state == kQRunLoopOperationStateExecuting;
-}
- 
-- (BOOL)isFinished
-{
-    // any thread
-    return self.state == kQRunLoopOperationStateFinished;
-}
-
-- (void)start
-{
-    // any thread
-
-    assert(self.state == kQRunLoopOperationStateInited);
-    
-    // We have to change the state here, otherwise isExecuting won't necessarily return 
-    // true by the time we return from -start.  Also, we don't test for cancellation 
-    // here because that would a) result in us sending isFinished notifications on a 
-    // thread that isn't our run loop thread, and b) confuse the core cancellation code, 
-    // which expects to run on our run loop thread.  Finally, we don't have to worry 
-    // about races with other threads calling -start.  Only one thread is allowed to 
-    // start us at a time.
-    
-    self.state = kQRunLoopOperationStateExecuting;
-    [self performSelector:@selector(startOnRunLoopThread) onThread:self.actualRunLoopThread withObject:nil waitUntilDone:NO modes:[self.actualRunLoopModes allObjects]];
-}
-
-- (void)cancel
-{
-    BOOL    runCancelOnRunLoopThread;
-    BOOL    oldValue;
-
-    // any thread
-
-    // We need to synchronise here to avoid state changes to isCancelled and state
-    // while we're running.
-    
-    @synchronized (self) {
-        oldValue = [self isCancelled];
-        
-        // Call our super class so that isCancelled starts returning true immediately.
-        
-        [super cancel];
-        
-        // If we were the one to set isCancelled (that is, we won the race with regards 
-        // other threads calling -cancel) and we're actually running (that is, we lost 
-        // the race with other threads calling -start and the run loop thread finishing), 
-        // we schedule to run on the run loop thread.
-
-        runCancelOnRunLoopThread = ! oldValue && self.state == kQRunLoopOperationStateExecuting;
-    }
-    if (runCancelOnRunLoopThread) {
-        [self performSelector:@selector(cancelOnRunLoopThread) onThread:self.actualRunLoopThread withObject:nil waitUntilDone:YES modes:[self.actualRunLoopModes allObjects]];
-    }
-}
-
-@end

+ 56 - 0
Example/AFHTTPRequestOperation.h

@@ -0,0 +1,56 @@
+// AFHTTPOperation.h
+//
+// Copyright (c) 2011 Gowalla (http://gowalla.com/)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Foundation/Foundation.h>
+
+extern NSString * const AFHTTPOperationDidStartNotification;
+extern NSString * const AFHTTPOperationDidFinishNotification;
+
+@interface AFHTTPRequestOperation : NSOperation <NSURLConnectionDelegate, NSURLConnectionDataDelegate> {
+@private    
+    NSURLConnection *_connection;
+    NSPort *_port;
+    NSSet *_runLoopModes;
+    
+    NSURLRequest *_request;
+    NSHTTPURLResponse *_response;
+    
+    NSData *_responseBody;
+    NSMutableData *_dataAccumulator;
+}
+
+@property (nonatomic, retain) NSURLConnection *connection;
+@property (nonatomic, retain) NSSet *runLoopModes;
+
+@property (nonatomic, retain) NSURLRequest *request;
+@property (nonatomic, retain) NSHTTPURLResponse *response;
+@property (nonatomic, retain) NSError *error;
+
+@property (nonatomic, retain) NSData *responseBody;
+@property (readonly) NSString *responseString;
+
++ (id)operationWithRequest:(NSURLRequest *)urlRequest 
+                completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error))completion;
+
+- (id)initWithRequest:(NSURLRequest *)urlRequest;
+
+@end

+ 269 - 0
Example/AFHTTPRequestOperation.m

@@ -0,0 +1,269 @@
+// AFHTTPOperation.m
+//
+// Copyright (c) 2011 Gowalla (http://gowalla.com/)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "AFHTTPRequestOperation.h"
+#import "AFNetworkActivityIndicatorManager.h"
+
+typedef enum {
+    AFHTTPOperationReadyState       = 1,
+    AFHTTPOperationExecutingState   = 2,
+    AFHTTPOperationFinishedState    = 3,
+    AFHTTPOperationCancelledState   = 4,
+} AFHTTPOperationState;
+
+NSString * const AFHTTPOperationDidStartNotification = @"com.alamofire.http-operation.start";
+NSString * const AFHTTPOperationDidFinishNotification = @"com.alamofire.http-operation.finish";
+
+typedef void (^AFHTTPRequestOperationCompletionBlock)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error);
+
+static inline NSString * AFKeyPathFromOperationState(AFHTTPOperationState state) {
+    switch (state) {
+        case AFHTTPOperationReadyState:
+            return @"isReady";
+        case AFHTTPOperationExecutingState:
+            return @"isExecuting";
+        case AFHTTPOperationFinishedState:
+        case AFHTTPOperationCancelledState:
+            return @"isFinished";
+        default:
+            return @"state";
+    }
+}
+
+static inline BOOL AFHTTPOperationStateTransitionIsValid(AFHTTPOperationState from, AFHTTPOperationState to) {
+    if (from == to) {
+        return NO;
+    }
+    
+    switch (from) {
+        case AFHTTPOperationReadyState:
+            switch (to) {
+                case AFHTTPOperationExecutingState:
+                case AFHTTPOperationCancelledState:
+                    return YES;
+                default:
+                    return NO;
+            }
+        case AFHTTPOperationExecutingState:
+            switch (to) {
+                case AFHTTPOperationReadyState:
+                    return NO;
+                default:
+                    return YES;
+            }
+        case AFHTTPOperationFinishedState:
+        case AFHTTPOperationCancelledState:
+            return NO;
+        default:
+            return YES;
+    }
+}
+
+@interface AFHTTPRequestOperation ()
+@property (nonatomic, assign) AFHTTPOperationState state;
+@property (readwrite, nonatomic, retain) NSPort *port;
+@property (readwrite, nonatomic, retain) NSMutableData *dataAccumulator;
+@property (readwrite, nonatomic, copy) AFHTTPRequestOperationCompletionBlock completion;
+@end
+
+@implementation AFHTTPRequestOperation
+@synthesize state = _state;
+@synthesize connection = _connection;
+@synthesize runLoopModes = _runLoopModes;
+@synthesize port = _port;
+@synthesize request = _request;
+@synthesize response = _response;
+@synthesize error = _error;
+@synthesize responseBody = _responseBody;
+@synthesize dataAccumulator = _dataAccumulator;
+@synthesize completion = _completion;
+
++ (id)operationWithRequest:(NSURLRequest *)urlRequest 
+                completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error))completion
+{
+    AFHTTPRequestOperation *operation = [[[self alloc] initWithRequest:urlRequest] autorelease];
+    operation.completion = completion;
+    
+    return operation;
+}
+
+- (id)initWithRequest:(NSURLRequest *)urlRequest {
+    self = [super init];
+    if (!self) {
+		return nil;
+    }
+        
+    self.request = urlRequest;
+	
+    self.runLoopModes = [NSSet setWithObjects:NSDefaultRunLoopMode, NSRunLoopCommonModes, nil];
+        
+    self.state = AFHTTPOperationReadyState;
+	
+    return self;
+}
+
+- (void)dealloc {
+    [_runLoopModes release];
+    [_port release];
+    
+    [_request release];
+    [_response release];
+    [_responseBody release];
+    [_dataAccumulator release];
+    
+    [_connection release];
+	
+    [_completion release];
+    [super dealloc];
+}
+
+- (void)setState:(AFHTTPOperationState)state {
+    if (!AFHTTPOperationStateTransitionIsValid(self.state, state)) {
+        return;
+    }
+    
+    NSString *oldStateKey = AFKeyPathFromOperationState(self.state);
+    NSString *newStateKey = AFKeyPathFromOperationState(state);
+    
+    [self willChangeValueForKey:newStateKey];
+    [self willChangeValueForKey:oldStateKey];
+    _state = state;
+    [self didChangeValueForKey:oldStateKey];
+    [self didChangeValueForKey:newStateKey];
+    
+    switch (state) {
+        case AFHTTPOperationExecutingState:
+            [[AFNetworkActivityIndicatorManager sharedManager] startAnimating];
+            [[NSNotificationCenter defaultCenter] postNotificationName:AFHTTPOperationDidStartNotification object:self];
+            break;
+        case AFHTTPOperationFinishedState:
+        case AFHTTPOperationCancelledState:
+            [[AFNetworkActivityIndicatorManager sharedManager] stopAnimating];
+            [[NSNotificationCenter defaultCenter] postNotificationName:AFHTTPOperationDidFinishNotification object:self];
+            
+            for (NSString *runLoopMode in self.runLoopModes) {
+                [[NSRunLoop currentRunLoop] removePort:self.port forMode:runLoopMode];
+                [self.connection unscheduleFromRunLoop:[NSRunLoop currentRunLoop] forMode:runLoopMode];
+            }
+            CFRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]);
+            break;
+        default:
+            break;
+    }
+}
+
+- (NSString *)responseString {
+    return [[[NSString alloc] initWithData:self.responseBody encoding:NSUTF8StringEncoding] autorelease];
+}
+
+#pragma mark - NSOperation
+
+- (BOOL)isReady {
+    return self.state == AFHTTPOperationReadyState;
+}
+
+- (BOOL)isExecuting {
+    return self.state == AFHTTPOperationExecutingState;
+}
+
+- (BOOL)isFinished {
+    return self.state == AFHTTPOperationFinishedState || self.isCancelled;
+}
+
+- (BOOL)isCancelled {
+    return self.state == AFHTTPOperationCancelledState;
+}
+
+- (BOOL)isConcurrent {
+    return YES;
+}
+
+- (void)start {
+    if (self.isFinished) {
+        return;
+    }
+    
+    self.state = AFHTTPOperationExecutingState;
+        
+    self.connection = [[[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO] autorelease];
+    self.port = [NSPort port];
+    
+    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
+    for (NSString *runLoopMode in self.runLoopModes) {
+        [self.connection scheduleInRunLoop:runLoop forMode:runLoopMode];
+        [runLoop addPort:self.port forMode:runLoopMode];
+    }
+    
+    [self.connection start];
+
+    [runLoop run];
+}
+
+- (void)cancel {    
+    self.state = AFHTTPOperationCancelledState;
+
+    [self.connection cancel];
+}
+
+#pragma mark - AFHTTPRequestOperation
+
+- (void)finish {
+    if (self.isCancelled) {
+        return;
+    }
+    
+    if (self.completion) {
+        self.completion(self.request, self.response, self.responseBody, self.error);
+    }
+}
+
+#pragma mark - NSURLConnection
+
+- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
+    self.response = (NSHTTPURLResponse *)response;
+    NSUInteger contentLength = MIN(MAX(abs(response.expectedContentLength), 1024), 1024 * 1024 * 8);
+
+    self.dataAccumulator = [NSMutableData dataWithCapacity:contentLength];
+}
+
+- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
+	[self.dataAccumulator appendData:data];
+}
+
+- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
+    self.state = AFHTTPOperationFinishedState;
+    
+    self.responseBody = [NSData dataWithData:self.dataAccumulator];
+    self.dataAccumulator = nil;
+
+    [self performSelectorOnMainThread:@selector(finish) withObject:nil waitUntilDone:YES modes:[self.runLoopModes allObjects]];
+}
+
+- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {  
+    self.state = AFHTTPOperationFinishedState;
+    
+    self.error = error;
+    
+    [self performSelectorOnMainThread:@selector(finish) withObject:nil waitUntilDone:YES modes:[self.runLoopModes allObjects]];
+}
+
+@end

+ 13 - 13
Example/Classes/AFImageRequest.h → Example/AFImageCache.h

@@ -1,4 +1,4 @@
-// AFImageRequest.h
+// AFImageCache.h
 //
 // Copyright (c) 2011 Gowalla (http://gowalla.com/)
 // 
@@ -20,20 +20,20 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
+#import <Foundation/Foundation.h>
 #import "AFImageRequestOperation.h"
 
-@protocol AFImageRequester
-@required
-- (void)setImageURLString:(NSString *)urlString;
-- (void)setImageURLString:(NSString *)urlString options:(AFImageRequestOptions)options;
-@optional
-@property (nonatomic, copy) NSString *imageURLString;
-@end
+@interface AFImageCache : NSCache
+
++ (id)sharedImageCache;
+
+- (UIImage *)cachedImageForRequest:(NSURLRequest *)urlRequest
+                         imageSize:(CGSize)imageSize
+                           options:(AFImageRequestOptions)options;
 
-@interface AFImageRequest : NSObject
+- (void)cacheImage:(UIImage *)image
+        forRequest:(NSURLRequest *)urlRequest
+         imageSize:(CGSize)imageSize
+           options:(AFImageRequestOptions)options;
 
-+ (void)requestImageWithURLString:(NSString *)urlString options:(AFImageRequestOptions)options block:(void (^)(UIImage *image))block;
-+ (void)requestImageWithURLString:(NSString *)urlString size:(CGSize)imageSize options:(AFImageRequestOptions)options block:(void (^)(UIImage *image))block;
-+ (void)cancelImageRequestOperationsForURLString:(NSString *)urlString;
-+ (void)cancelAllImageRequestOperations;
 @end

+ 60 - 0
Example/AFImageCache.m

@@ -0,0 +1,60 @@
+// AFImageCache.m
+//
+// Copyright (c) 2011 Gowalla (http://gowalla.com/)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "AFImageCache.h"
+
+static inline NSString * AFImageCacheKey(NSURLRequest *urlRequest, CGSize imageSize, AFImageRequestOptions options) {
+    return [[[urlRequest URL] absoluteString] stringByAppendingFormat:@"#%fx%f:%d", imageSize.width, imageSize.height, options];
+}
+
+@implementation AFImageCache
+
++ (id)sharedImageCache {
+    static NSCache *_sharedImageCache = nil;
+    
+    if (!_sharedImageCache) {
+        _sharedImageCache = [[self alloc] init];
+    }
+    
+    return _sharedImageCache;
+}
+
+- (UIImage *)cachedImageForRequest:(NSURLRequest *)urlRequest
+                         imageSize:(CGSize)imageSize
+                           options:(AFImageRequestOptions)options
+{
+    return [self objectForKey:AFImageCacheKey(urlRequest, imageSize, options)];
+}
+
+- (void)cacheImage:(UIImage *)image
+        forRequest:(NSURLRequest *)urlRequest
+         imageSize:(CGSize)imageSize
+           options:(AFImageRequestOptions)options
+{
+    if (!image) {
+        return;
+    }
+    
+    [self setObject:image forKey:AFImageCacheKey(urlRequest, imageSize, options)];
+}
+
+@end

+ 42 - 0
Example/AFImageRequestOperation.h

@@ -0,0 +1,42 @@
+// AFImageRequestOperation.h
+//
+// Copyright (c) 2011 Gowalla (http://gowalla.com/)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+#import "AFHTTPRequestOperation.h"
+
+typedef enum {
+    AFImageRequestDefaultOptions        = 0,
+    AFImageRequestRoundCorners			= 1 << 1,
+} AFImageRequestOptions;
+
+@interface AFImageRequestOperation : AFHTTPRequestOperation
+
++ (id)operationWithRequest:(NSURLRequest *)urlRequest                
+                   success:(void (^)(UIImage *image))success;
+
++ (id)operationWithRequest:(NSURLRequest *)urlRequest
+                 imageSize:(CGSize)imageSize
+                   options:(AFImageRequestOptions)options
+                   success:(void (^)(UIImage *image))success;
+
+@end

+ 88 - 0
Example/AFImageRequestOperation.m

@@ -0,0 +1,88 @@
+// AFImageRequestOperation.m
+//
+// Copyright (c) 2011 Gowalla (http://gowalla.com/)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "AFImageRequestOperation.h"
+#import "AFImageCache.h"
+
+#import "UIImage+AFNetworking.h"
+
+static CGFloat const kAFImageRequestJPEGQuality = 0.8;
+static NSUInteger const kAFImageRequestMaximumResponseSize = 8 * 1024 * 1024;
+
+static inline CGSize kAFImageRequestRoundedCornerRadii(CGSize imageSize) {
+    CGFloat dimension = fmaxf(imageSize.width, imageSize.height) * 0.1;
+    return CGSizeMake(dimension, dimension);
+}
+
+@implementation AFImageRequestOperation
+
++ (id)operationWithRequest:(NSURLRequest *)urlRequest                
+                   success:(void (^)(UIImage *image))success
+{
+    return [self operationWithRequest:urlRequest imageSize:CGSizeZero options:AFImageRequestDefaultOptions success:success];
+}
+
++ (id)operationWithRequest:(NSURLRequest *)urlRequest
+                 imageSize:(CGSize)imageSize
+                   options:(AFImageRequestOptions)options
+                   success:(void (^)(UIImage *image))success
+{
+    return [self operationWithRequest:urlRequest completion:^(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error) {
+        UIImage *image = nil;    
+        if ([[UIScreen mainScreen] scale] == 2.0) {
+            CGImageRef imageRef = [[UIImage imageWithData:data] CGImage];
+            image = [UIImage imageWithCGImage:imageRef scale:2.0 orientation:UIImageOrientationUp];
+        } else {
+            image = [UIImage imageWithData:data]; 
+        }
+        
+        if (!(CGSizeEqualToSize(image.size, imageSize) || CGSizeEqualToSize(imageSize, CGSizeZero))) {
+            image = [UIImage imageByScalingAndCroppingImage:image size:imageSize];
+        }
+        if ((options & AFImageRequestRoundCorners)) {
+            image = [UIImage imageByRoundingCornersOfImage:image corners:UIRectCornerAllCorners cornerRadii:kAFImageRequestRoundedCornerRadii(image.size)];
+        }
+        
+        dispatch_async(dispatch_get_main_queue(), ^(void) {
+            if (success) {
+                success(image);
+            }
+        });
+        
+        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
+            [[AFImageCache sharedImageCache] cacheImage:image forRequest:request imageSize:imageSize options:options];
+        });
+    }];
+}
+
+- (id)initWithRequest:(NSURLRequest *)urlRequest {
+    self = [super initWithRequest:urlRequest];
+    if (!self) {
+        return nil;
+    }
+    
+    self.runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes];
+    
+    return self;
+}
+
+@end

+ 14 - 34
AFNetworking/AFCallback.m → Example/AFJSONRequestOperation.h

@@ -1,4 +1,4 @@
-// AFCallback.m
+// AFJSONRequestOperation.h
 //
 // Copyright (c) 2011 Gowalla (http://gowalla.com/)
 // 
@@ -20,41 +20,21 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#import "AFCallback.h"
+#import "AFHTTPRequestOperation.h"
 
-@interface AFCallback ()
-@property (readwrite, nonatomic, copy) id successBlock;
-@property (readwrite, nonatomic, copy) id errorBlock;
-@end
-
-@implementation AFCallback
-@synthesize successBlock = _successBlock;
-@synthesize errorBlock = _errorBlock;
+@interface AFJSONRequestOperation : AFHTTPRequestOperation
 
-+ (id)callbackWithSuccess:(id)success {
-	return [self callbackWithSuccess:success error:nil];
-}
++ (id)operationWithRequest:(NSURLRequest *)urlRequest                
+                   success:(void (^)(NSDictionary *JSON))success;
 
-+ (id)callbackWithSuccess:(id)success error:(id)error {
-	id callback = [[[self alloc] init] autorelease];
-	[callback setSuccessBlock:success];
-	[callback setErrorBlock:error];
-	
-	return callback;
-}
++ (id)operationWithRequest:(NSURLRequest *)urlRequest 
+                   success:(void (^)(NSDictionary *JSON))success
+                   failure:(void (^)(NSError *error))failure;
 
-- (id)init {
-	if ([self class] == [AFCallback class]) {
-		[NSException raise:NSInternalInconsistencyException format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];
-	}
-	
-	return [super init];
-}
++ (id)operationWithRequest:(NSURLRequest *)urlRequest
+     acceptableStatusCodes:(NSIndexSet *)acceptableStatusCodes
+    acceptableContentTypes:(NSSet *)acceptableContentTypes
+                   success:(void (^)(NSDictionary *JSON))success
+                   failure:(void (^)(NSError *error))failure;
 
-- (void)dealloc {
-	[_successBlock release];
-	[_errorBlock release];
-	[super dealloc];
-}
-
-@end
+@end

+ 75 - 0
Example/AFJSONRequestOperation.m

@@ -0,0 +1,75 @@
+// AFJSONRequestOperation.m
+//
+// Copyright (c) 2011 Gowalla (http://gowalla.com/)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "AFJSONRequestOperation.h"
+#import "JSONKit.h"
+
+@implementation AFJSONRequestOperation
+
++ (id)operationWithRequest:(NSURLRequest *)urlRequest                
+                   success:(void (^)(NSDictionary *JSON))success
+{
+    return [self operationWithRequest:urlRequest success:success failure:nil];
+}
+
++ (id)operationWithRequest:(NSURLRequest *)urlRequest 
+                   success:(void (^)(NSDictionary *JSON))success
+                   failure:(void (^)(NSError *error))failure
+{
+    NSIndexSet *acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)];
+    NSSet *acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"application/x-javascript", @"text/javascript", @"text/x-javascript", @"text/x-json", @"text/plain", nil];
+    
+    return [self operationWithRequest:urlRequest acceptableStatusCodes:acceptableStatusCodes acceptableContentTypes:acceptableContentTypes success:success failure:failure];
+}
+
++ (id)operationWithRequest:(NSURLRequest *)urlRequest
+     acceptableStatusCodes:(NSIndexSet *)acceptableStatusCodes
+    acceptableContentTypes:(NSSet *)acceptableContentTypes
+                   success:(void (^)(NSDictionary *JSON))success
+                   failure:(void (^)(NSError *error))failure
+{
+    return [self operationWithRequest:urlRequest completion:^(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error) {        
+        BOOL statusCodeAcceptable = [acceptableStatusCodes containsIndex:[response statusCode]];
+        BOOL contentTypeAcceptable = [acceptableContentTypes containsObject:[response MIMEType]];
+        if (!statusCodeAcceptable || !contentTypeAcceptable) {
+            NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+            [userInfo setValue:[NSHTTPURLResponse localizedStringForStatusCode:[response statusCode]] forKey:NSLocalizedDescriptionKey];
+            [userInfo setValue:[request URL] forKey:NSURLErrorFailingURLErrorKey];
+            
+            error = [[[NSError alloc] initWithDomain:NSURLErrorDomain code:[response statusCode] userInfo:userInfo] autorelease];
+        }
+        
+        if (error) {
+            if (failure) {
+                failure(error);
+            }
+        } else {
+            NSDictionary *JSON = [[JSONDecoder decoder] objectWithData:data error:&error];
+            
+            if (success) {
+                success(JSON);
+            }
+        }
+    }];
+}
+
+@end

+ 9 - 10
AFNetworking/AFCallback.h → Example/AFNetworkActivityIndicatorManager.h

@@ -1,4 +1,4 @@
-// AFCallback.h
+// AFNetworkActivityIndicatorManager.h
 //
 // Copyright (c) 2011 Gowalla (http://gowalla.com/)
 // 
@@ -22,15 +22,14 @@
 
 #import <Foundation/Foundation.h>
 
-@protocol AFCallback <NSObject>
-+ (id)callbackWithSuccess:(id)success;
-+ (id)callbackWithSuccess:(id)success error:(id)error;
-@end
-
-@interface AFCallback : NSObject <AFCallback> {
+@interface AFNetworkActivityIndicatorManager : NSObject {
 @private
-	id _successBlock;
-	id _errorBlock;
+	NSUInteger _activityCount;
 }
 
-@end
++ (AFNetworkActivityIndicatorManager *)sharedManager;
+
+- (void)startAnimating;
+- (void)stopAnimating;
+
+@end

+ 57 - 0
Example/AFNetworkActivityIndicatorManager.m

@@ -0,0 +1,57 @@
+// AFNetworkActivityIndicatorManager.m
+//
+// Copyright (c) 2011 Gowalla (http://gowalla.com/)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "AFNetworkActivityIndicatorManager.h"
+
+@interface AFNetworkActivityIndicatorManager ()
+@property (readwrite, nonatomic, assign) NSUInteger activityCount;
+@end
+
+@implementation AFNetworkActivityIndicatorManager
+@synthesize activityCount = _activityCount;
+
++ (AFNetworkActivityIndicatorManager *)sharedManager {
+    static AFNetworkActivityIndicatorManager *_sharedManager = nil;
+    if (!_sharedManager) {
+        _sharedManager = [[AFNetworkActivityIndicatorManager alloc] init];
+    }
+    
+    return _sharedManager;
+}
+
+- (void)setActivityCount:(NSUInteger)activityCount {
+    [self willChangeValueForKey:@"activityCount"];
+    _activityCount = MAX(activityCount, 0);
+    [self didChangeValueForKey:@"activityCount"];
+
+    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:self.activityCount > 0];
+}
+
+- (void)startAnimating {
+	self.activityCount += 1;
+}
+
+- (void)stopAnimating {
+    self.activityCount -= 1;
+}
+
+@end

+ 49 - 57
Example/AFNetworking Example.xcodeproj/project.pbxproj

@@ -7,20 +7,20 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		F874B5B113E0937400B28E3E /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5A413E0937400B28E3E /* AFHTTPRequestOperation.m */; };
+		F874B5B213E0937400B28E3E /* AFJSONRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5A613E0937400B28E3E /* AFJSONRequestOperation.m */; };
+		F874B5B313E0937400B28E3E /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5A813E0937400B28E3E /* AFImageRequestOperation.m */; };
+		F874B5B413E0937400B28E3E /* AFImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5AA13E0937400B28E3E /* AFImageCache.m */; };
+		F874B5B513E0937400B28E3E /* AFRestClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5AC13E0937400B28E3E /* AFRestClient.m */; };
+		F874B5B613E0937400B28E3E /* UIImage+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5AE13E0937400B28E3E /* UIImage+AFNetworking.m */; };
+		F874B5B713E0937400B28E3E /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5B013E0937400B28E3E /* UIImageView+AFNetworking.m */; };
+		F874B5BA13E096C400B28E3E /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5B913E096C400B28E3E /* AFNetworkActivityIndicatorManager.m */; };
 		F8D25D191396A9D300CF3BD6 /* placeholder-stamp.png in Resources */ = {isa = PBXBuildFile; fileRef = F8D25D171396A9D300CF3BD6 /* placeholder-stamp.png */; };
 		F8D25D1A1396A9D300CF3BD6 /* placeholder-stamp@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F8D25D181396A9D300CF3BD6 /* placeholder-stamp@2x.png */; };
 		F8DA09D21396ABED0057D0CC /* AFGowallaAPIClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D25D1D1396A9DE00CF3BD6 /* AFGowallaAPIClient.m */; };
-		F8DA09D31396ABED0057D0CC /* AFImageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D25D1E1396A9DE00CF3BD6 /* AFImageRequest.m */; };
 		F8DA09D41396ABED0057D0CC /* NearbySpotsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F8DA09C81396AB690057D0CC /* NearbySpotsViewController.m */; };
 		F8DA09D51396ABED0057D0CC /* Spot.m in Sources */ = {isa = PBXBuildFile; fileRef = F8DA09CB1396AB690057D0CC /* Spot.m */; };
 		F8DA09D61396ABED0057D0CC /* SpotTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F8DA09CE1396AB690057D0CC /* SpotTableViewCell.m */; };
-		F8DA09D91396ABED0057D0CC /* AFCallback.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D25CF01396A98600CF3BD6 /* AFCallback.m */; };
-		F8DA09DA1396ABED0057D0CC /* AFHTTPOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D25CF11396A98600CF3BD6 /* AFHTTPOperation.m */; };
-		F8DA09DB1396ABED0057D0CC /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D25CF21396A98600CF3BD6 /* AFImageRequestOperation.m */; };
-		F8DA09DC1396ABED0057D0CC /* AFRestClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D25CF31396A98600CF3BD6 /* AFRestClient.m */; };
-		F8DA09DE1396ABED0057D0CC /* UIImage+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D25CF51396A98600CF3BD6 /* UIImage+AFNetworking.m */; };
-		F8DA09DF1396ABED0057D0CC /* QHTTPOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D25D0A1396A9A900CF3BD6 /* QHTTPOperation.m */; };
-		F8DA09E01396ABED0057D0CC /* QRunLoopOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D25D0C1396A9A900CF3BD6 /* QRunLoopOperation.m */; };
 		F8DA09E11396ABED0057D0CC /* JSONKit.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D25D111396A9C400CF3BD6 /* JSONKit.m */; };
 		F8DA09E21396ABED0057D0CC /* TTTLocationFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D25D141396A9C400CF3BD6 /* TTTLocationFormatter.m */; };
 		F8DA09E41396AC040057D0CC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F8DA09E31396AC040057D0CC /* main.m */; };
@@ -32,20 +32,22 @@
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
-		F8D25CEA1396A98600CF3BD6 /* AFCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFCallback.h; path = ../AFNetworking/AFCallback.h; sourceTree = "<group>"; };
-		F8D25CEB1396A98600CF3BD6 /* AFHTTPOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFHTTPOperation.h; path = ../AFNetworking/AFHTTPOperation.h; sourceTree = "<group>"; };
-		F8D25CEC1396A98600CF3BD6 /* AFImageRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFImageRequestOperation.h; path = ../AFNetworking/AFImageRequestOperation.h; sourceTree = "<group>"; };
-		F8D25CED1396A98600CF3BD6 /* AFRestClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFRestClient.h; path = ../AFNetworking/AFRestClient.h; sourceTree = "<group>"; };
-		F8D25CEF1396A98600CF3BD6 /* UIImage+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImage+AFNetworking.h"; path = "../AFNetworking/UIImage+AFNetworking.h"; sourceTree = "<group>"; };
-		F8D25CF01396A98600CF3BD6 /* AFCallback.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFCallback.m; path = ../AFNetworking/AFCallback.m; sourceTree = "<group>"; };
-		F8D25CF11396A98600CF3BD6 /* AFHTTPOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFHTTPOperation.m; path = ../AFNetworking/AFHTTPOperation.m; sourceTree = "<group>"; };
-		F8D25CF21396A98600CF3BD6 /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageRequestOperation.m; path = ../AFNetworking/AFImageRequestOperation.m; sourceTree = "<group>"; };
-		F8D25CF31396A98600CF3BD6 /* AFRestClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFRestClient.m; path = ../AFNetworking/AFRestClient.m; sourceTree = "<group>"; };
-		F8D25CF51396A98600CF3BD6 /* UIImage+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImage+AFNetworking.m"; path = "../AFNetworking/UIImage+AFNetworking.m"; sourceTree = "<group>"; };
-		F8D25D091396A9A900CF3BD6 /* QHTTPOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QHTTPOperation.h; sourceTree = "<group>"; };
-		F8D25D0A1396A9A900CF3BD6 /* QHTTPOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QHTTPOperation.m; sourceTree = "<group>"; };
-		F8D25D0B1396A9A900CF3BD6 /* QRunLoopOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QRunLoopOperation.h; sourceTree = "<group>"; };
-		F8D25D0C1396A9A900CF3BD6 /* QRunLoopOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QRunLoopOperation.m; sourceTree = "<group>"; };
+		F874B5A313E0937400B28E3E /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPRequestOperation.h; sourceTree = "<group>"; };
+		F874B5A413E0937400B28E3E /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperation.m; sourceTree = "<group>"; };
+		F874B5A513E0937400B28E3E /* AFJSONRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFJSONRequestOperation.h; sourceTree = "<group>"; };
+		F874B5A613E0937400B28E3E /* AFJSONRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFJSONRequestOperation.m; sourceTree = "<group>"; };
+		F874B5A713E0937400B28E3E /* AFImageRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFImageRequestOperation.h; sourceTree = "<group>"; };
+		F874B5A813E0937400B28E3E /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFImageRequestOperation.m; sourceTree = "<group>"; };
+		F874B5A913E0937400B28E3E /* AFImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFImageCache.h; sourceTree = "<group>"; };
+		F874B5AA13E0937400B28E3E /* AFImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFImageCache.m; sourceTree = "<group>"; };
+		F874B5AB13E0937400B28E3E /* AFRestClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFRestClient.h; sourceTree = "<group>"; };
+		F874B5AC13E0937400B28E3E /* AFRestClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFRestClient.m; sourceTree = "<group>"; };
+		F874B5AD13E0937400B28E3E /* UIImage+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+AFNetworking.h"; sourceTree = "<group>"; };
+		F874B5AE13E0937400B28E3E /* UIImage+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+AFNetworking.m"; sourceTree = "<group>"; };
+		F874B5AF13E0937400B28E3E /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+AFNetworking.h"; sourceTree = "<group>"; };
+		F874B5B013E0937400B28E3E /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+AFNetworking.m"; sourceTree = "<group>"; };
+		F874B5B813E096C400B28E3E /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworkActivityIndicatorManager.h; sourceTree = "<group>"; };
+		F874B5B913E096C400B28E3E /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFNetworkActivityIndicatorManager.m; sourceTree = "<group>"; };
 		F8D25D101396A9C400CF3BD6 /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = "<group>"; };
 		F8D25D111396A9C400CF3BD6 /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = "<group>"; };
 		F8D25D131396A9C400CF3BD6 /* TTTLocationFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TTTLocationFormatter.h; sourceTree = "<group>"; };
@@ -53,9 +55,7 @@
 		F8D25D171396A9D300CF3BD6 /* placeholder-stamp.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "placeholder-stamp.png"; path = "Images/placeholder-stamp.png"; sourceTree = SOURCE_ROOT; };
 		F8D25D181396A9D300CF3BD6 /* placeholder-stamp@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "placeholder-stamp@2x.png"; path = "Images/placeholder-stamp@2x.png"; sourceTree = SOURCE_ROOT; };
 		F8D25D1B1396A9DE00CF3BD6 /* AFGowallaAPIClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFGowallaAPIClient.h; path = Classes/AFGowallaAPIClient.h; sourceTree = "<group>"; };
-		F8D25D1C1396A9DE00CF3BD6 /* AFImageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFImageRequest.h; path = Classes/AFImageRequest.h; sourceTree = "<group>"; };
 		F8D25D1D1396A9DE00CF3BD6 /* AFGowallaAPIClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFGowallaAPIClient.m; path = Classes/AFGowallaAPIClient.m; sourceTree = "<group>"; };
-		F8D25D1E1396A9DE00CF3BD6 /* AFImageRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageRequest.m; path = Classes/AFImageRequest.m; sourceTree = "<group>"; };
 		F8DA09C71396AB690057D0CC /* NearbySpotsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NearbySpotsViewController.h; sourceTree = "<group>"; };
 		F8DA09C81396AB690057D0CC /* NearbySpotsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NearbySpotsViewController.m; sourceTree = "<group>"; };
 		F8DA09CA1396AB690057D0CC /* Spot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Spot.h; sourceTree = "<group>"; };
@@ -92,18 +92,6 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
-		F8D25D081396A9A900CF3BD6 /* QHTTPOperation */ = {
-			isa = PBXGroup;
-			children = (
-				F8D25D091396A9A900CF3BD6 /* QHTTPOperation.h */,
-				F8D25D0A1396A9A900CF3BD6 /* QHTTPOperation.m */,
-				F8D25D0B1396A9A900CF3BD6 /* QRunLoopOperation.h */,
-				F8D25D0C1396A9A900CF3BD6 /* QRunLoopOperation.m */,
-			);
-			name = QHTTPOperation;
-			path = ../AFNetworking/QHTTPOperation;
-			sourceTree = "<group>";
-		};
 		F8D25D0F1396A9C400CF3BD6 /* JSONKit */ = {
 			isa = PBXGroup;
 			children = (
@@ -216,7 +204,6 @@
 			isa = PBXGroup;
 			children = (
 				F8E469941395744600DB05C8 /* Alamofire */,
-				F8D25D081396A9A900CF3BD6 /* QHTTPOperation */,
 				F8D25D0F1396A9C400CF3BD6 /* JSONKit */,
 				F8D25D121396A9C400CF3BD6 /* TTT */,
 			);
@@ -226,16 +213,22 @@
 		F8E469941395744600DB05C8 /* Alamofire */ = {
 			isa = PBXGroup;
 			children = (
-				F8D25CEA1396A98600CF3BD6 /* AFCallback.h */,
-				F8D25CF01396A98600CF3BD6 /* AFCallback.m */,
-				F8D25CEB1396A98600CF3BD6 /* AFHTTPOperation.h */,
-				F8D25CF11396A98600CF3BD6 /* AFHTTPOperation.m */,
-				F8D25CEC1396A98600CF3BD6 /* AFImageRequestOperation.h */,
-				F8D25CF21396A98600CF3BD6 /* AFImageRequestOperation.m */,
-				F8D25CED1396A98600CF3BD6 /* AFRestClient.h */,
-				F8D25CF31396A98600CF3BD6 /* AFRestClient.m */,
-				F8D25CEF1396A98600CF3BD6 /* UIImage+AFNetworking.h */,
-				F8D25CF51396A98600CF3BD6 /* UIImage+AFNetworking.m */,
+				F874B5A313E0937400B28E3E /* AFHTTPRequestOperation.h */,
+				F874B5A413E0937400B28E3E /* AFHTTPRequestOperation.m */,
+				F874B5A513E0937400B28E3E /* AFJSONRequestOperation.h */,
+				F874B5A613E0937400B28E3E /* AFJSONRequestOperation.m */,
+				F874B5AB13E0937400B28E3E /* AFRestClient.h */,
+				F874B5AC13E0937400B28E3E /* AFRestClient.m */,
+				F874B5A713E0937400B28E3E /* AFImageRequestOperation.h */,
+				F874B5A813E0937400B28E3E /* AFImageRequestOperation.m */,
+				F874B5A913E0937400B28E3E /* AFImageCache.h */,
+				F874B5AA13E0937400B28E3E /* AFImageCache.m */,
+				F874B5B813E096C400B28E3E /* AFNetworkActivityIndicatorManager.h */,
+				F874B5B913E096C400B28E3E /* AFNetworkActivityIndicatorManager.m */,
+				F874B5AD13E0937400B28E3E /* UIImage+AFNetworking.h */,
+				F874B5AE13E0937400B28E3E /* UIImage+AFNetworking.m */,
+				F874B5AF13E0937400B28E3E /* UIImageView+AFNetworking.h */,
+				F874B5B013E0937400B28E3E /* UIImageView+AFNetworking.m */,
 			);
 			name = Alamofire;
 			sourceTree = "<group>";
@@ -245,8 +238,6 @@
 			children = (
 				F8D25D1B1396A9DE00CF3BD6 /* AFGowallaAPIClient.h */,
 				F8D25D1D1396A9DE00CF3BD6 /* AFGowallaAPIClient.m */,
-				F8D25D1C1396A9DE00CF3BD6 /* AFImageRequest.h */,
-				F8D25D1E1396A9DE00CF3BD6 /* AFImageRequest.m */,
 			);
 			name = "Networking Extensions";
 			sourceTree = "<group>";
@@ -287,6 +278,7 @@
 		F8E469571395739C00DB05C8 /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
+				LastUpgradeCheck = 0420;
 				ORGANIZATIONNAME = Gowalla;
 			};
 			buildConfigurationList = F8E4695A1395739C00DB05C8 /* Build configuration list for PBXProject "AFNetworking Example" */;
@@ -324,21 +316,21 @@
 			buildActionMask = 2147483647;
 			files = (
 				F8DA09D21396ABED0057D0CC /* AFGowallaAPIClient.m in Sources */,
-				F8DA09D31396ABED0057D0CC /* AFImageRequest.m in Sources */,
 				F8DA09D41396ABED0057D0CC /* NearbySpotsViewController.m in Sources */,
 				F8DA09D51396ABED0057D0CC /* Spot.m in Sources */,
 				F8DA09D61396ABED0057D0CC /* SpotTableViewCell.m in Sources */,
-				F8DA09D91396ABED0057D0CC /* AFCallback.m in Sources */,
-				F8DA09DA1396ABED0057D0CC /* AFHTTPOperation.m in Sources */,
-				F8DA09DB1396ABED0057D0CC /* AFImageRequestOperation.m in Sources */,
-				F8DA09DC1396ABED0057D0CC /* AFRestClient.m in Sources */,
-				F8DA09DE1396ABED0057D0CC /* UIImage+AFNetworking.m in Sources */,
-				F8DA09DF1396ABED0057D0CC /* QHTTPOperation.m in Sources */,
-				F8DA09E01396ABED0057D0CC /* QRunLoopOperation.m in Sources */,
 				F8DA09E11396ABED0057D0CC /* JSONKit.m in Sources */,
 				F8DA09E21396ABED0057D0CC /* TTTLocationFormatter.m in Sources */,
 				F8DA09E41396AC040057D0CC /* main.m in Sources */,
 				F8DA09E81396AC220057D0CC /* AppDelegate.m in Sources */,
+				F874B5B113E0937400B28E3E /* AFHTTPRequestOperation.m in Sources */,
+				F874B5B213E0937400B28E3E /* AFJSONRequestOperation.m in Sources */,
+				F874B5B313E0937400B28E3E /* AFImageRequestOperation.m in Sources */,
+				F874B5B413E0937400B28E3E /* AFImageCache.m in Sources */,
+				F874B5B513E0937400B28E3E /* AFRestClient.m in Sources */,
+				F874B5B613E0937400B28E3E /* UIImage+AFNetworking.m in Sources */,
+				F874B5B713E0937400B28E3E /* UIImageView+AFNetworking.m in Sources */,
+				F874B5BA13E096C400B28E3E /* AFNetworkActivityIndicatorManager.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Diferenças do arquivo suprimidas por serem muito extensas
+ 327 - 294
Example/AFNetworking Example.xcodeproj/project.xcworkspace/xcuserdata/mattt.xcuserdatad/UserInterfaceState.xcuserstate


+ 16 - 0
Example/AFNetworking Example.xcodeproj/xcuserdata/mattt.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist

@@ -2,4 +2,20 @@
 <Bucket
    type = "1"
    version = "1.0">
+   <FileBreakpoints>
+      <FileBreakpoint
+         shouldBeEnabled = "No"
+         ignoreCount = "0"
+         continueAfterRunningActions = "No"
+         isPathRelative = "0"
+         filePath = "/Users/mattt/Code/Objective-C/AFNetworking/AFNetworking/AFImageRequestOperation.m"
+         timestampString = "332372128.476073"
+         startingColumnNumber = "9223372036854775807"
+         endingColumnNumber = "9223372036854775807"
+         startingLineNumber = "86"
+         endingLineNumber = "86"
+         landmarkName = "-finish"
+         landmarkType = "5">
+      </FileBreakpoint>
+   </FileBreakpoints>
 </Bucket>

+ 20 - 10
AFNetworking/AFRestClient.h → Example/AFRestClient.h

@@ -21,27 +21,37 @@
 // THE SOFTWARE.
 
 #import <Foundation/Foundation.h>
-#import "AFHTTPOperation.h"
+#import "AFHTTPRequestOperation.h"
 
 @protocol AFRestClient <NSObject>
-@required
 + (NSURL *)baseURL;
-- (NSMutableURLRequest *)requestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters;
 @end
 
-@interface AFRestClient : NSObject <AFRestClient>
+@interface AFRestClient : NSObject <AFRestClient> {
+@protected
+    NSMutableDictionary *_defaultHeaders;
+    NSOperationQueue *_operationQueue;
+}
+
 - (NSString *)defaultValueForHeader:(NSString *)header;
 - (void)setDefaultHeader:(NSString *)header value:(NSString *)value;
 - (void)setAuthorizationHeaderWithToken:(NSString *)token;
 - (void)clearAuthorizationHeader;
 
-- (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters callback:(AFHTTPOperationCallback *)callback;
-- (void)postPath:(NSString *)path parameters:(NSDictionary *)parameters callback:(AFHTTPOperationCallback *)callback;
-- (void)putPath:(NSString *)path parameters:(NSDictionary *)parameters callback:(AFHTTPOperationCallback *)callback;
-- (void)deletePath:(NSString *)path parameters:(NSDictionary *)parameters callback:(AFHTTPOperationCallback *)callback;
+- (NSMutableURLRequest *)requestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters;
+- (void)enqueueHTTPOperationWithRequest:(NSURLRequest *)request success:(void (^)(NSDictionary *response))success failure:(void (^)(NSError *error))failure;
+
+- (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *response))success;
+- (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *response))success failure:(void (^)(NSError *error))failure;
+
+- (void)postPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *response))success;
+- (void)postPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *response))success failure:(void (^)(NSError *error))failure;
+
+- (void)putPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *response))success;
+- (void)putPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *response))success failure:(void (^)(NSError *error))failure;
 
-- (void)enqueueHTTPOperationWithRequest:(NSURLRequest *)request callback:(AFHTTPOperationCallback *)callback;
-- (void)enqueueHTTPOperation:(AFHTTPOperation *)operation;
+- (void)deletePath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *response))success;
+- (void)deletePath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *response))success failure:(void (^)(NSError *error))failure;
 @end
 
 #pragma mark - NSString + AFRestClient

+ 64 - 53
AFNetworking/AFRestClient.m → Example/AFRestClient.m

@@ -21,13 +21,15 @@
 // THE SOFTWARE.
 
 #import "AFRestClient.h"
-#import "AFHTTPOperation.h"
+#import "AFJSONRequestOperation.h"
 
 static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding;
 
 @interface AFRestClient ()
 @property (readwrite, nonatomic, retain) NSMutableDictionary *defaultHeaders;
 @property (readwrite, nonatomic, retain) NSOperationQueue *operationQueue;
+
+- (void)enqueueHTTPOperationWithRequest:(NSURLRequest *)request success:(void (^)(NSDictionary *response))success failure:(void (^)(NSError *error))failure;
 @end
 
 @implementation AFRestClient
@@ -78,36 +80,6 @@ static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding
     return nil;
 }
 
-- (NSMutableURLRequest *)requestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters {	
-	NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
-	NSMutableDictionary *headers = [NSMutableDictionary dictionaryWithDictionary:_defaultHeaders];
-	NSURL *url = nil;
-	
-	NSMutableArray *mutableParameterComponents = [NSMutableArray array];
-	for (id key in [parameters allKeys]) {
-		NSString *component = [NSString stringWithFormat:@"%@=%@", [key urlEncodedStringWithEncoding:kAFRestClientStringEncoding], [[parameters valueForKey:key] urlEncodedStringWithEncoding:kAFRestClientStringEncoding]];
-		[mutableParameterComponents addObject:component];
-	}
-	NSString *queryString = [mutableParameterComponents componentsJoinedByString:@"&"];
-    
-	if ([method isEqualToString:@"GET"]) {
-		path = [path stringByAppendingFormat:[path rangeOfString:@"?"].location == NSNotFound ? @"?%@" : @"&%@", queryString];
-		url = [NSURL URLWithString:path relativeToURL:[[self class] baseURL]];
-	} else {
-		url = [NSURL URLWithString:path relativeToURL:[[self class] baseURL]];
-		NSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(kAFRestClientStringEncoding));
-		[headers setObject:[NSString stringWithFormat:@"application/x-www-form-urlencoded; charset=%@", charset] forKey:@"Content-Type"];
-		[request setHTTPBody:[queryString dataUsingEncoding:NSUTF8StringEncoding]];
-	}
-    
-	[request setURL:url];
-	[request setHTTPMethod:method];
-	[request setHTTPShouldHandleCookies:NO];
-	[request setAllHTTPHeaderFields:headers];
-    
-	return request;
-}
-
 - (NSString *)defaultValueForHeader:(NSString *)header {
 	return [self.defaultHeaders valueForKey:header];
 }
@@ -124,42 +96,81 @@ static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding
 	[self.defaultHeaders removeObjectForKey:@"Authorization"];
 }
 
-
 #pragma mark -
 
-- (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters callback:(AFHTTPOperationCallback *)callback {
+- (NSMutableURLRequest *)requestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters {	
+	NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
+	NSMutableDictionary *headers = [NSMutableDictionary dictionaryWithDictionary:self.defaultHeaders];
+	NSURL *url = [NSURL URLWithString:path relativeToURL:[[self class] baseURL]];
+	
+    if (parameters) {
+        NSMutableArray *mutableParameterComponents = [NSMutableArray array];
+        for (id key in [parameters allKeys]) {
+            NSString *component = [NSString stringWithFormat:@"%@=%@", [key urlEncodedStringWithEncoding:kAFRestClientStringEncoding], [[parameters valueForKey:key] urlEncodedStringWithEncoding:kAFRestClientStringEncoding]];
+            [mutableParameterComponents addObject:component];
+        }
+        NSString *queryString = [mutableParameterComponents componentsJoinedByString:@"&"];
+        
+        if ([method isEqualToString:@"GET"]) {
+            url = [NSURL URLWithString:[[url absoluteString] stringByAppendingFormat:[path rangeOfString:@"?"].location == NSNotFound ? @"?%@" : @"&%@", queryString]];
+        } else {
+            NSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(kAFRestClientStringEncoding));
+            [headers setObject:[NSString stringWithFormat:@"application/x-www-form-urlencoded; charset=%@", charset] forKey:@"Content-Type"];
+            [request setHTTPBody:[queryString dataUsingEncoding:NSUTF8StringEncoding]];
+        }
+    }
+    
+	[request setURL:url];
+	[request setHTTPMethod:method];
+	[request setHTTPShouldHandleCookies:NO];
+	[request setAllHTTPHeaderFields:headers];
+    
+	return request;
+}
+
+- (void)enqueueHTTPOperationWithRequest:(NSURLRequest *)request success:(void (^)(NSDictionary *response))success failure:(void (^)(NSError *error))failure {
+	if ([request URL] == nil || [[request URL] isEqual:[NSNull null]]) {
+		return;
+	}
+    
+    AFHTTPRequestOperation *operation = [AFJSONRequestOperation operationWithRequest:request success:success failure:failure];
+    [self.operationQueue addOperation:operation];
+}
+
+- (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *))success {
+    [self getPath:path parameters:parameters success:success failure:nil];
+}
+
+- (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *))success failure:(void (^)(NSError *error))failure {
 	NSURLRequest *request = [self requestWithMethod:@"GET" path:path parameters:parameters];
-	[self enqueueHTTPOperationWithRequest:request callback:callback];
+	[self enqueueHTTPOperationWithRequest:request success:success failure:failure];
 }
 
-- (void)postPath:(NSString *)path parameters:(NSDictionary *)parameters callback:(AFHTTPOperationCallback *)callback  {
-	NSURLRequest *request = [self requestWithMethod:@"POST" path:path parameters:parameters];
-	[self enqueueHTTPOperationWithRequest:request callback:callback];
+- (void)postPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *))success {
+    [self postPath:path parameters:parameters success:success failure:nil];
 }
 
-- (void)putPath:(NSString *)path parameters:(NSDictionary *)parameters callback:(AFHTTPOperationCallback *)callback  {
-	NSURLRequest *request = [self requestWithMethod:@"PUT" path:path parameters:parameters];
-	[self enqueueHTTPOperationWithRequest:request callback:callback];
+- (void)postPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *))success failure:(void (^)(NSError *error))failure {
+	NSURLRequest *request = [self requestWithMethod:@"POST" path:path parameters:parameters];
+	[self enqueueHTTPOperationWithRequest:request success:success failure:failure];
 }
 
-- (void)deletePath:(NSString *)path parameters:(NSDictionary *)parameters callback:(AFHTTPOperationCallback *)callback  {
-	NSURLRequest *request = [self requestWithMethod:@"DELETE" path:path parameters:parameters];
-	[self enqueueHTTPOperationWithRequest:request callback:callback];
+- (void)putPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *))success {
+    [self putPath:path parameters:parameters success:success failure:nil];
 }
 
-#pragma mark -
+- (void)putPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *))success failure:(void (^)(NSError *error))failure {
+	NSURLRequest *request = [self requestWithMethod:@"PUT" path:path parameters:parameters];
+	[self enqueueHTTPOperationWithRequest:request success:success failure:failure];
+}
 
-- (void)enqueueHTTPOperationWithRequest:(NSURLRequest *)request callback:(AFHTTPOperationCallback *)callback {
-	if ([request URL] == nil || [[request URL] isEqual:[NSNull null]]) {
-		return;
-	}
-	
-	AFHTTPOperation *operation = [[[AFHTTPOperation alloc] initWithRequest:request callback:callback] autorelease];
-    [self enqueueHTTPOperation:operation];
+- (void)deletePath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *))success {
+    [self deletePath:path parameters:parameters success:success failure:nil];
 }
 
-- (void)enqueueHTTPOperation:(AFHTTPOperation *)operation {
-    [self.operationQueue addOperation:operation];
+- (void)deletePath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSDictionary *))success failure:(void (^)(NSError *error))failure {
+	NSURLRequest *request = [self requestWithMethod:@"DELETE" path:path parameters:parameters];
+	[self enqueueHTTPOperationWithRequest:request success:success failure:failure];
 }
 
 @end

+ 0 - 94
Example/Classes/AFImageRequest.m

@@ -1,94 +0,0 @@
-// AFImageRequest.m
-//
-// Copyright (c) 2011 Gowalla (http://gowalla.com/)
-// 
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-// 
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#import "AFImageRequest.h"
-#import "AFImageRequestOperation.h"
-
-static NSOperationQueue *_operationQueue = nil;
-static NSMutableSet *_cachedRequests = nil;
-
-@implementation AFImageRequest
-
-+ (void)initialize {
-	_operationQueue = [[NSOperationQueue alloc] init];
-	[_operationQueue setMaxConcurrentOperationCount:6];
-	
-    _cachedRequests = [[NSMutableSet alloc] init];
-}
-
-+ (void)requestImageWithURLString:(NSString *)urlString options:(AFImageRequestOptions)options block:(void (^)(UIImage *image))block {
-	[self requestImageWithURLString:urlString size:CGSizeZero options:options block:block];
-}
-
-+ (void)requestImageWithURLString:(NSString *)urlString size:(CGSize)imageSize options:(AFImageRequestOptions)options block:(void (^)(UIImage *image))block {
-	// Append a hash anchor to the image URL so that unique image options get cached separately
-    NSString *cacheAnchor = [NSString stringWithFormat:@"%fx%f:%d", imageSize.width, imageSize.height, options];
-	NSURL *url = [NSURL URLWithString:[urlString stringByAppendingString:[NSString stringWithFormat:@"#%@", cacheAnchor]]];
-	if (!url) {
-		if (block) {
-			block(nil);
-		}
-		return;
-	}
-	
-	NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLCacheStorageAllowed timeoutInterval:30.0];
-	[request setHTTPShouldHandleCookies:NO];
-	
-	AFImageRequestOperationCallback *callback = [AFImageRequestOperationCallback callbackWithSuccess:block imageSize:imageSize options:options];
-	AFImageRequestOperation *operation = [[[AFImageRequestOperation alloc] initWithRequest:request callback:callback] autorelease];
-	
-	NSCachedURLResponse *cachedResponse = [[[[NSURLCache sharedURLCache] cachedResponseForRequest:request] retain] autorelease];
-	if (cachedResponse) {
-		if (block) {
-			block([UIImage imageWithData:[cachedResponse data]]);
-			return;
-		}
-	}
-	
-	[_operationQueue addOperation:operation];
-}
-
-+ (void)cancelImageRequestOperationsForURLString:(NSString *)urlString {
-    if (!urlString) {
-        return;
-    }
-    
-    for (AFImageRequestOperation *operation in [_operationQueue operations]) {
-        NSString *requestURLString = [[[operation request] URL] absoluteString];
-        NSRange anchorRange = [requestURLString rangeOfString:@"#" options:NSBackwardsSearch];
-        if (anchorRange.location != NSNotFound && [[requestURLString substringToIndex:anchorRange.location] isEqualToString:urlString]) {
-            if (!([operation isExecuting] || [operation isCancelled])) {
-                [operation cancel];
-            }
-        }
-    }
-}
-
-+ (void)cancelAllImageRequestOperations {
-    for (AFImageRequestOperation *operation in [_operationQueue operations]) {
-        if (!([operation isExecuting] || [operation isCancelled])) {
-            [operation cancel];
-        }
-    }  
-}
-
-@end

+ 14 - 8
Example/Classes/Controllers/NearbySpotsViewController.m

@@ -21,9 +21,14 @@
 // THE SOFTWARE.
 
 #import "NearbySpotsViewController.h"
+
 #import "Spot.h"
+
 #import "SpotTableViewCell.h"
+
 #import "TTTLocationFormatter.h"
+#import "AFImageCache.h"
+#import "UIImageView+AFNetworking.h"
 
 @interface NearbySpotsViewController ()
 @property (readwrite, nonatomic, retain) NSArray *nearbySpots;
@@ -72,7 +77,7 @@ static TTTLocationFormatter *__locationFormatter;
     [self.activityIndicatorView startAnimating];
     self.navigationItem.rightBarButtonItem.enabled = NO;
     
-    [Spot spotsWithURLString:@"/spots/advanced_search" near:location parameters:[NSDictionary dictionaryWithObject:@"128" forKey:@"per_page"] withBlock:^(NSArray *records) {
+    [Spot spotsWithURLString:@"/spots/advanced_search" near:location parameters:[NSDictionary dictionaryWithObject:@"128" forKey:@"per_page"] block:^(NSArray *records) {
         self.nearbySpots = [records sortedArrayUsingComparator:^ NSComparisonResult(id obj1, id obj2) {
             CLLocationDistance d1 = [[(Spot *)obj1 location] distanceFromLocation:location];
             CLLocationDistance d2 = [[(Spot *)obj2 location] distanceFromLocation:location];
@@ -119,24 +124,25 @@ static TTTLocationFormatter *__locationFormatter;
     [self.locationManager stopUpdatingLocation];
 }
 
-#pragma mark - CLLocationManagerDelegate
-
-- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
-    [self loadSpotsForLocation:newLocation];
-}
-
 #pragma mark - Actions
 
 - (void)refresh:(id)sender {
     self.nearbySpots = [NSArray array];
     [self.tableView reloadData];
     [[NSURLCache sharedURLCache] removeAllCachedResponses];
+    [[AFImageCache sharedImageCache] removeAllObjects];
     
     if (self.locationManager.location) {
         [self loadSpotsForLocation:self.locationManager.location];
     }
 }
 
+#pragma mark - CLLocationManagerDelegate
+
+- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
+    [self loadSpotsForLocation:newLocation];
+}
+
 #pragma mark - UITableViewDelegate
 
 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
@@ -160,7 +166,7 @@ static TTTLocationFormatter *__locationFormatter;
     if (self.locationManager.location) {
         cell.detailTextLabel.text = [__locationFormatter stringFromDistanceAndBearingFromLocation:self.locationManager.location toLocation:spot.location];
     }
-    cell.imageURLString = spot.imageURLString;
+    [cell.imageView setImageWithURL:[NSURL URLWithString:spot.imageURLString] placeholderImage:[UIImage imageNamed:@"placeholder-stamp.png"]];
     
     return cell;
 }

+ 1 - 1
Example/Classes/Models/Spot.h

@@ -40,6 +40,6 @@ typedef void (^AFRecordsBlock)(NSArray *records);
 @property (readonly) CLLocation *location;
 
 - (id)initWithAttributes:(NSDictionary *)attributes;
-+ (void)spotsWithURLString:(NSString *)urlString near:(CLLocation *)location parameters:(NSDictionary *)parameters withBlock:(AFRecordsBlock)block;
++ (void)spotsWithURLString:(NSString *)urlString near:(CLLocation *)location parameters:(NSDictionary *)parameters block:(AFRecordsBlock)block;
 
 @end

+ 14 - 10
Example/Classes/Models/Spot.m

@@ -56,24 +56,28 @@
     return [[[CLLocation alloc] initWithLatitude:[self.latitude doubleValue] longitude:[self.longitude doubleValue]] autorelease];
 }
 
-+ (void)spotsWithURLString:(NSString *)urlString near:(CLLocation *)location parameters:(NSDictionary *)parameters withBlock:(AFRecordsBlock)block {
++ (void)spotsWithURLString:(NSString *)urlString near:(CLLocation *)location parameters:(NSDictionary *)parameters block:(AFRecordsBlock)block {
     NSDictionary *mutableParameters = [NSMutableDictionary dictionaryWithDictionary:parameters];
 	if (location) {
 		[mutableParameters setValue:[NSString stringWithFormat:@"%1.7f", location.coordinate.latitude] forKey:@"lat"];
 		[mutableParameters setValue:[NSString stringWithFormat:@"%1.7f", location.coordinate.longitude] forKey:@"lng"];
 	}
     
-    [[AFGowallaAPIClient sharedClient] getPath:urlString parameters:mutableParameters callback:[AFHTTPOperationCallback callbackWithSuccess:^(NSURLRequest *request, NSHTTPURLResponse *response, NSDictionary *data) {
-		if (block) {
-            NSMutableArray *mutableRecords = [NSMutableArray array];
-            for (NSDictionary *attributes in [data valueForKeyPath:@"spots"]) {
-                Spot *spot = [[[Spot alloc] initWithAttributes:attributes] autorelease];
-                [mutableRecords addObject:spot];
-            }
-            
+    [[AFGowallaAPIClient sharedClient] getPath:urlString parameters:mutableParameters success:^(NSDictionary *response) {
+        NSMutableArray *mutableRecords = [NSMutableArray array];
+        for (NSDictionary *attributes in [response valueForKeyPath:@"spots"]) {
+            Spot *spot = [[[Spot alloc] initWithAttributes:attributes] autorelease];
+            [mutableRecords addObject:spot];
+        }
+        
+        if (block) {
             block([NSArray arrayWithArray:mutableRecords]);
         }
-	}]];
+    } failure:^(NSError *error) {
+        if (block) {
+            block([NSArray array]);
+        }
+    }];
 }
 
 @end

+ 1 - 4
Example/Classes/Views/SpotTableViewCell.h

@@ -21,10 +21,7 @@
 // THE SOFTWARE.
 
 #import <UIKit/UIKit.h>
-#import "AFImageRequest.h"
 
-@interface SpotTableViewCell : UITableViewCell <AFImageRequester> {
-    NSString *_imageURLString;
-}
+@interface SpotTableViewCell : UITableViewCell
 
 @end

+ 0 - 45
Example/Classes/Views/SpotTableViewCell.m

@@ -23,7 +23,6 @@
 #import "SpotTableViewCell.h"
 
 @implementation SpotTableViewCell
-@synthesize imageURLString = _imageURLString;
 
 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
     self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
@@ -41,50 +40,6 @@
     return self;
 }
 
-- (void)dealloc {
-    [_imageURLString release];
-    [super dealloc];
-}
-
-- (void)setImageURLString:(NSString *)imageURLString {
-    [self setImageURLString:imageURLString options:AFImageRequestResize | AFImageCacheProcessedImage];
-}
-
-- (void)setImageURLString:(NSString *)imageURLString options:(AFImageRequestOptions)options {
-	if ([self.imageURLString isEqual:imageURLString]) {
-		return;
-	}
-    
-	if (self.imageURLString) {
-		self.imageView.image = [UIImage imageNamed:@"placeholder-stamp.png"];
-	}
-	
-	[self willChangeValueForKey:@"imageURLString"];
-	[_imageURLString release];
-	_imageURLString = [imageURLString copy];
-	[self didChangeValueForKey:@"imageURLString"];
-	
-	if (self.imageURLString) {
-		[AFImageRequest requestImageWithURLString:self.imageURLString size:CGSizeMake(50.0f, 50.0f) options:options block:^(UIImage *image) {
-			if ([self.imageURLString isEqualToString:imageURLString]) {
-				BOOL needsLayout = self.imageView.image == nil;
-                self.imageView.image = image;
-				
-				if (needsLayout) {
-					[self setNeedsLayout];
-				}
-            }
-		}];
-	}
-}
-
-#pragma mark - UITableViewCell
-
-- (void)prepareForReuse {
-    [super prepareForReuse];
-    [AFImageRequest cancelImageRequestOperationsForURLString:self.imageURLString];
-}
-
 #pragma mark - UIView
 
 - (void)layoutSubviews {

+ 0 - 0
AFNetworking/UIImage+AFNetworking.h → Example/UIImage+AFNetworking.h


+ 0 - 1
AFNetworking/UIImage+AFNetworking.m → Example/UIImage+AFNetworking.m

@@ -75,7 +75,6 @@
     UIGraphicsEndImageContext();
     
     return newImage;
-
 }
 
 @end

+ 32 - 0
Example/UIImageView+AFNetworking.h

@@ -0,0 +1,32 @@
+// UIImageView+AFNetworking.h
+//
+// Copyright (c) 2011 Gowalla (http://gowalla.com/)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <UIKit/UIKit.h>
+#import "AFImageRequestOperation.h"
+
+@interface UIImageView (AFNetworking)
+
+- (void)setImageWithURL:(NSURL *)url;
+- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage;
+- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage imageSize:(CGSize)imageSize options:(AFImageRequestOptions)options;
+
+@end

+ 101 - 0
Example/UIImageView+AFNetworking.m

@@ -0,0 +1,101 @@
+// UIImageView+AFNetworking.m
+//
+// Copyright (c) 2011 Gowalla (http://gowalla.com/)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "UIImageView+AFNetworking.h"
+
+#import "AFImageCache.h"
+
+static NSOperationQueue *_operationQueue = nil;
+
+static NSString * const kUIImageViewImageRequestObjectKey = @"imageRequestOperation";
+
+@interface UIImageView (_AFNetworking)
+@property (readwrite, nonatomic, retain) AFImageRequestOperation *imageRequestOperation;
+@end
+
+@implementation UIImageView (_AFNetworking)
+@dynamic imageRequestOperation;
+@end
+
+#pragma mark -
+
+@implementation UIImageView (AFNetworking)
+
+- (AFHTTPRequestOperation *)imageRequestOperation {
+    return objc_getAssociatedObject(self, kUIImageViewImageRequestObjectKey);
+}
+
+- (void)setImageRequestOperation:(AFImageRequestOperation *)imageRequestOperation {
+    objc_setAssociatedObject(self, kUIImageViewImageRequestObjectKey, imageRequestOperation, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
++ (void)initialize {
+    [super initialize];
+    
+	_operationQueue = [[NSOperationQueue alloc] init];
+	[_operationQueue setMaxConcurrentOperationCount:6];
+}
+ 
+- (void)setImageWithURL:(NSURL *)url {
+    [self setImageWithURL:url placeholderImage:nil];
+}
+
+- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage {
+    [self setImageWithURL:url placeholderImage:placeholderImage imageSize:self.frame.size options:AFImageRequestDefaultOptions];
+}
+
+- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage imageSize:(CGSize)imageSize options:(AFImageRequestOptions)options {
+    if (!url) {
+        return;
+    }
+    
+    if (self.imageRequestOperation && ([self.imageRequestOperation isReady] || [self.imageRequestOperation isExecuting])) {
+        if ([[[self.imageRequestOperation request] URL] isEqual:url]) {
+            return;
+        } else {
+            [self.imageRequestOperation cancel]; 
+        }
+    }
+    
+    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLCacheStorageAllowed timeoutInterval:30.0];
+    [request setHTTPShouldHandleCookies:NO];
+        
+    UIImage *cachedImage = [[AFImageCache sharedImageCache] cachedImageForRequest:request imageSize:imageSize options:options];
+    if (cachedImage) {
+        self.image = cachedImage;
+    } else {
+        self.image = placeholderImage;
+        
+        self.imageRequestOperation = [AFImageRequestOperation operationWithRequest:request imageSize:imageSize options:options success:^(UIImage *image) {
+            if ([[request URL] isEqual:[[self.imageRequestOperation request] URL]]) {
+                self.image = image;
+            } else {
+                self.image = placeholderImage;
+            }
+        }];
+        
+        [_operationQueue addOperation:self.imageRequestOperation];
+    }
+}
+
+
+@end

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff