From 50014afa2214226d021917983821259f86dbb673 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 16 Sep 2011 22:40:52 -0500 Subject: [PATCH 01/41] Refactoring image request API to remove unnecessary configuration, and focus the design goals of those classes --- AFNetworking/AFImageCache.h | 6 +-- AFNetworking/AFImageCache.m | 16 +++--- AFNetworking/AFImageRequestOperation.h | 12 ++--- AFNetworking/AFImageRequestOperation.m | 68 ++++++++++++------------- AFNetworking/UIImageView+AFNetworking.h | 9 +--- AFNetworking/UIImageView+AFNetworking.m | 50 +++++++++--------- 6 files changed, 74 insertions(+), 87 deletions(-) diff --git a/AFNetworking/AFImageCache.h b/AFNetworking/AFImageCache.h index 8cbe227..35b10b3 100644 --- a/AFNetworking/AFImageCache.h +++ b/AFNetworking/AFImageCache.h @@ -28,12 +28,10 @@ + (id)sharedImageCache; - (UIImage *)cachedImageForRequest:(NSURLRequest *)urlRequest - imageSize:(CGSize)imageSize - options:(AFImageRequestOptions)options; + cacheName:(NSString *)cacheName; - (void)cacheImage:(UIImage *)image forRequest:(NSURLRequest *)urlRequest - imageSize:(CGSize)imageSize - options:(AFImageRequestOptions)options; + cacheName:(NSString *)cacheName; @end diff --git a/AFNetworking/AFImageCache.m b/AFNetworking/AFImageCache.m index d83d111..521a788 100644 --- a/AFNetworking/AFImageCache.m +++ b/AFNetworking/AFImageCache.m @@ -22,8 +22,8 @@ #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]; +static inline NSString * AFImageCacheKey(NSURLRequest *urlRequest, NSString *cacheName) { + return [[[urlRequest URL] absoluteString] stringByAppendingFormat:@"#%@", cacheName]; } @implementation AFImageCache @@ -40,22 +40,20 @@ static inline NSString * AFImageCacheKey(NSURLRequest *urlRequest, CGSize imageS } - (UIImage *)cachedImageForRequest:(NSURLRequest *)urlRequest - imageSize:(CGSize)imageSize - options:(AFImageRequestOptions)options + cacheName:(NSString *)cacheName { - return [self objectForKey:AFImageCacheKey(urlRequest, imageSize, options)]; + return [self objectForKey:AFImageCacheKey(urlRequest, cacheName)]; } - (void)cacheImage:(UIImage *)image forRequest:(NSURLRequest *)urlRequest - imageSize:(CGSize)imageSize - options:(AFImageRequestOptions)options + cacheName:(NSString *)cacheName { if (!image) { return; } - - [self setObject:image forKey:AFImageCacheKey(urlRequest, imageSize, options)]; + + [self setObject:image forKey:AFImageCacheKey(urlRequest, cacheName)]; } @end diff --git a/AFNetworking/AFImageRequestOperation.h b/AFNetworking/AFImageRequestOperation.h index 8c0f48c..ccb2039 100644 --- a/AFNetworking/AFImageRequestOperation.h +++ b/AFNetworking/AFImageRequestOperation.h @@ -24,19 +24,15 @@ #import #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; + imageProcessingBlock:(UIImage *(^)(UIImage *))imageProcessingBlock + cacheName:(NSString *)cacheNameOrNil + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; @end diff --git a/AFNetworking/AFImageRequestOperation.m b/AFNetworking/AFImageRequestOperation.m index 1dd8899..b2f70e0 100644 --- a/AFNetworking/AFImageRequestOperation.m +++ b/AFNetworking/AFImageRequestOperation.m @@ -25,14 +25,6 @@ #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); -} - static dispatch_queue_t af_image_request_operation_processing_queue; static dispatch_queue_t image_request_operation_processing_queue() { if (af_image_request_operation_processing_queue == NULL) { @@ -47,42 +39,48 @@ static dispatch_queue_t image_request_operation_processing_queue() { + (id)operationWithRequest:(NSURLRequest *)urlRequest success:(void (^)(UIImage *image))success { - return [self operationWithRequest:urlRequest imageSize:CGSizeZero options:AFImageRequestDefaultOptions success:success]; + return [self operationWithRequest:urlRequest imageProcessingBlock:nil cacheName:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { + if (success) { + success(image); + } + } failure:nil]; } + (id)operationWithRequest:(NSURLRequest *)urlRequest - imageSize:(CGSize)imageSize - options:(AFImageRequestOptions)options - success:(void (^)(UIImage *image))success + imageProcessingBlock:(UIImage *(^)(UIImage *))imageProcessingBlock + cacheName:(NSString *)cacheNameOrNil + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure { AFImageRequestOperation *operation = [self operationWithRequest:urlRequest completion:^(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error) { dispatch_async(image_request_operation_processing_queue(), ^(void) { - 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_sync(dispatch_get_main_queue(), ^(void) { - if (success) { - success(image); + if (error) { + if (failure) { + failure(request, response, error); } - }); - - [[AFImageCache sharedImageCache] cacheImage:image forRequest:request imageSize:imageSize options:options]; + } else { + 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 (imageProcessingBlock) { + image = imageProcessingBlock(image); + } + + dispatch_sync(dispatch_get_main_queue(), ^(void) { + if (success) { + success(request, response, image); + } + }); + + [[AFImageCache sharedImageCache] cacheImage:image forRequest:request cacheName:cacheNameOrNil]; + } }); }]; - - operation.runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes]; return operation; } diff --git a/AFNetworking/UIImageView+AFNetworking.h b/AFNetworking/UIImageView+AFNetworking.h index b6deef6..d983f36 100644 --- a/AFNetworking/UIImageView+AFNetworking.h +++ b/AFNetworking/UIImageView+AFNetworking.h @@ -32,14 +32,7 @@ - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage - imageSize:(CGSize)imageSize - options:(AFImageRequestOptions)options; - -- (void)setImageWithURL:(NSURL *)url - placeholderImage:(UIImage *)placeholderImage - imageSize:(CGSize)imageSize - options:(AFImageRequestOptions)options - block:(void (^)(UIImage *image, BOOL cacheUsed))block; + success:(void (^)(UIImage *image, BOOL cacheUsed))block; - (void)cancelImageRequestOperation; diff --git a/AFNetworking/UIImageView+AFNetworking.m b/AFNetworking/UIImageView+AFNetworking.m index 62ea896..70dddd0 100644 --- a/AFNetworking/UIImageView+AFNetworking.m +++ b/AFNetworking/UIImageView+AFNetworking.m @@ -24,6 +24,7 @@ #import #import "UIImageView+AFNetworking.h" +#import "UIImage+AFNetworking.h" #import "AFImageCache.h" @@ -54,37 +55,27 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp if (!_imageRequestOperationQueue) { _imageRequestOperationQueue = [[NSOperationQueue alloc] init]; - [_imageRequestOperationQueue setMaxConcurrentOperationCount:6]; + [_imageRequestOperationQueue setMaxConcurrentOperationCount:8]; } return _imageRequestOperationQueue; } #pragma mark - - + - (void)setImageWithURL:(NSURL *)url { [self setImageWithURL:url placeholderImage:nil]; } - (void)setImageWithURL:(NSURL *)url - placeholderImage:(UIImage *)placeholderImage + placeholderImage:(UIImage *)placeholderImage { - [self setImageWithURL:url placeholderImage:placeholderImage imageSize:self.frame.size options:AFImageRequestDefaultOptions]; + [self setImageWithURL:url placeholderImage:placeholderImage success:nil]; } - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage - imageSize:(CGSize)imageSize - options:(AFImageRequestOptions)options -{ - [self setImageWithURL:url placeholderImage:placeholderImage imageSize:imageSize options:options block:nil]; -} - -- (void)setImageWithURL:(NSURL *)url - placeholderImage:(UIImage *)placeholderImage - imageSize:(CGSize)imageSize - options:(AFImageRequestOptions)options - block:(void (^)(UIImage *image, BOOL cacheUsed))block + success:(void (^)(UIImage *image, BOOL cacheUsed))success { if (!url || [url isEqual:self.imageRequestOperation.request.URL]) { return; @@ -96,30 +87,43 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp [request setHTTPShouldHandleCookies:NO]; [request setHTTPShouldUsePipelining:YES]; - UIImage *cachedImage = [[AFImageCache sharedImageCache] cachedImageForRequest:request imageSize:imageSize options:options]; + NSString *cacheName = @"UIImageView"; + if (placeholderImage) { + cacheName = [cacheName stringByAppendingFormat:@"(%@)", NSStringFromCGSize(placeholderImage.size)]; + } + + UIImage *cachedImage = [[AFImageCache sharedImageCache] cachedImageForRequest:request cacheName:cacheName]; if (cachedImage) { self.image = cachedImage; - if (block) { - block(cachedImage, YES); + if (success) { + success(cachedImage, YES); } } else { self.image = placeholderImage; - self.imageRequestOperation = [AFImageRequestOperation operationWithRequest:request imageSize:imageSize options:options success:^(UIImage *image) { + self.imageRequestOperation = [AFImageRequestOperation operationWithRequest:request imageProcessingBlock:^UIImage *(UIImage *image) { + if (placeholderImage) { + image = [UIImage imageByScalingAndCroppingImage:image size:placeholderImage.size]; + } + + return image; + } cacheName:cacheName success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { if (self.imageRequestOperation && ![self.imageRequestOperation isCancelled]) { - if (block) { - block(image, NO); + if (success) { + success(image, NO); } - + if ([[request URL] isEqual:[[self.imageRequestOperation request] URL]]) { self.image = image; } else { self.image = placeholderImage; } } + } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) { + self.imageRequestOperation = nil; }]; - + [[[self class] sharedImageRequestOperationQueue] addOperation:self.imageRequestOperation]; } } From 2610b0b57a843c8e92f2a165dd94fd0dfec598c2 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 16 Sep 2011 22:41:10 -0500 Subject: [PATCH 02/41] Minor refactoring to Location Formatter --- Example/Vendor/TTT/TTTLocationFormatter.m | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Example/Vendor/TTT/TTTLocationFormatter.m b/Example/Vendor/TTT/TTTLocationFormatter.m index 88089df..46894b8 100644 --- a/Example/Vendor/TTT/TTTLocationFormatter.m +++ b/Example/Vendor/TTT/TTTLocationFormatter.m @@ -159,13 +159,12 @@ static inline double CLLocationSpeedToMilesPerHour(CLLocationSpeed speed) { switch (self.unitSystem) { case TTTMetricSystem: { - double meterDistance = distance; - double kilometerDistance = CLLocationDistanceToKilometers(distance); - + double kilometerDistance = CLLocationDistanceToKilometers(distance); if (kilometerDistance > 1) { distanceString = [self.numberFormatter stringFromNumber:[NSNumber numberWithDouble:kilometerDistance]]; unitString = NSLocalizedString(@"km", @"Kilometer Unit"); } else { + double meterDistance = distance; distanceString = [self.numberFormatter stringFromNumber:[NSNumber numberWithDouble:meterDistance]]; unitString = NSLocalizedString(@"m", @"Meter Unit"); } @@ -174,18 +173,19 @@ static inline double CLLocationSpeedToMilesPerHour(CLLocationSpeed speed) { case TTTImperialSystem: { double feetDistance = CLLocationDistanceToFeet(distance); - double yardDistance = CLLocationDistanceToYards(distance); - double milesDistance = CLLocationDistanceToMiles(distance); - if (feetDistance < 300) { distanceString = [self.numberFormatter stringFromNumber:[NSNumber numberWithDouble:feetDistance]]; unitString = NSLocalizedString(@"ft", @"Feet Unit"); - } else if (yardDistance < 500) { - distanceString = [self.numberFormatter stringFromNumber:[NSNumber numberWithDouble:yardDistance]]; - unitString = NSLocalizedString(@"yds", @"Yard Unit"); } else { - distanceString = [self.numberFormatter stringFromNumber:[NSNumber numberWithDouble:milesDistance]]; - unitString = (milesDistance > 1.0 && milesDistance < 1.1) ? NSLocalizedString(@"mile", @"Mile Unit (Singular)") : NSLocalizedString(@"miles", @"Mile Unit (Plural)"); + double yardDistance = CLLocationDistanceToYards(distance); + if (yardDistance < 500) { + distanceString = [self.numberFormatter stringFromNumber:[NSNumber numberWithDouble:yardDistance]]; + unitString = NSLocalizedString(@"yds", @"Yard Unit"); + } else { + double milesDistance = CLLocationDistanceToMiles(distance); + distanceString = [self.numberFormatter stringFromNumber:[NSNumber numberWithDouble:milesDistance]]; + unitString = (milesDistance > 1.0 && milesDistance < 1.1) ? NSLocalizedString(@"mile", @"Mile Unit (Singular)") : NSLocalizedString(@"miles", @"Mile Unit (Plural)"); + } } break; } From 9ee84844c4e53e696320056675a9a5bb877a9db1 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 16 Sep 2011 22:41:21 -0500 Subject: [PATCH 03/41] Updating example project to new image request API --- .../project.pbxproj | 2 + .../xcschemes/AFNetworking Example.xcscheme | 14 +++- .../Controllers/NearbySpotsViewController.m | 8 +- Example/Classes/Views/SpotTableViewCell.h | 4 + Example/Classes/Views/SpotTableViewCell.m | 75 +++++++++++++------ 5 files changed, 76 insertions(+), 27 deletions(-) diff --git a/Example/AFNetworking Example.xcodeproj/project.pbxproj b/Example/AFNetworking Example.xcodeproj/project.pbxproj index b61798d..6b71fb1 100644 --- a/Example/AFNetworking Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking Example.xcodeproj/project.pbxproj @@ -58,6 +58,7 @@ F874B5D613E0AA6500B28E3E /* AFRestClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = AFRestClient.h; path = ../AFNetworking/AFRestClient.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; F874B5D713E0AA6500B28E3E /* UIImage+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImage+AFNetworking.h"; path = "../AFNetworking/UIImage+AFNetworking.h"; sourceTree = ""; }; F874B5D813E0AA6500B28E3E /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImageView+AFNetworking.h"; path = "../AFNetworking/UIImageView+AFNetworking.h"; sourceTree = ""; }; + F8870C3D1424409800BCD863 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; F8D25D101396A9C400CF3BD6 /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = ""; }; F8D25D111396A9C400CF3BD6 /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = ""; }; F8D25D131396A9C400CF3BD6 /* TTTLocationFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TTTLocationFormatter.h; sourceTree = ""; }; @@ -174,6 +175,7 @@ F8E469551395739C00DB05C8 = { isa = PBXGroup; children = ( + F8870C3D1424409800BCD863 /* QuartzCore.framework */, F8E469B71395759C00DB05C8 /* Networking Extensions */, F8E4696A1395739D00DB05C8 /* Classes */, F8E469ED1395812A00DB05C8 /* Images */, diff --git a/Example/AFNetworking Example.xcodeproj/xcuserdata/mattt.xcuserdatad/xcschemes/AFNetworking Example.xcscheme b/Example/AFNetworking Example.xcodeproj/xcuserdata/mattt.xcuserdatad/xcschemes/AFNetworking Example.xcscheme index 0f592ba..a8639b4 100644 --- a/Example/AFNetworking Example.xcodeproj/xcuserdata/mattt.xcuserdatad/xcschemes/AFNetworking Example.xcscheme +++ b/Example/AFNetworking Example.xcodeproj/xcuserdata/mattt.xcuserdatad/xcschemes/AFNetworking Example.xcscheme @@ -1,6 +1,6 @@ + version = "1.8"> @@ -36,7 +36,9 @@ displayScale = "1.00" launchStyle = "0" useCustomWorkingDirectory = "NO" - buildConfiguration = "Debug"> + buildConfiguration = "Debug" + debugDocumentVersioning = "YES" + allowLocationSimulation = "YES"> + + + buildConfiguration = "Release" + debugDocumentVersioning = "YES"> +@class Spot; + @interface SpotTableViewCell : UITableViewCell +@property (nonatomic, retain) Spot *spot; + @end diff --git a/Example/Classes/Views/SpotTableViewCell.m b/Example/Classes/Views/SpotTableViewCell.m index 5ecb303..5de7eb1 100644 --- a/Example/Classes/Views/SpotTableViewCell.m +++ b/Example/Classes/Views/SpotTableViewCell.m @@ -22,7 +22,12 @@ #import "SpotTableViewCell.h" +#import "Spot.h" + +#import "UIImageView+AFNetworking.h" + @implementation SpotTableViewCell +@synthesize spot = _spot; - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; @@ -32,35 +37,63 @@ self.textLabel.textColor = [UIColor darkGrayColor]; self.textLabel.numberOfLines = 2; + self.textLabel.backgroundColor = self.backgroundColor; self.detailTextLabel.textColor = [UIColor grayColor]; + self.detailTextLabel.backgroundColor = self.backgroundColor; + + self.imageView.backgroundColor = self.backgroundColor; self.selectionStyle = UITableViewCellSelectionStyleGray; return self; } -#pragma mark - UIView - -- (void)layoutSubviews { - [super layoutSubviews]; - - CGRect imageViewFrame = self.imageView.frame; - CGRect textLabelFrame = self.textLabel.frame; - CGRect detailTextLabelFrame = self.detailTextLabel.frame; - - imageViewFrame.origin = CGPointMake(10.0f, 10.0f); - imageViewFrame.size = CGSizeMake(50.0f, 50.0f); - - textLabelFrame.origin.x = imageViewFrame.size.width + 25.0f; - detailTextLabelFrame.origin.x = textLabelFrame.origin.x; - - textLabelFrame.size.width = 240.0f; - detailTextLabelFrame.size.width = textLabelFrame.size.width; - - self.textLabel.frame = textLabelFrame; - self.detailTextLabel.frame = detailTextLabelFrame; - self.imageView.frame = imageViewFrame; +- (void)dealloc { + [_spot release]; + [super dealloc]; } +- (void)setSpot:(Spot *)spot { + [self willChangeValueForKey:@"spot"]; + [_spot autorelease]; + _spot = [spot retain]; + [self didChangeValueForKey:@"spot"]; + + [self.imageView setImageWithURL:[NSURL URLWithString:self.spot.imageURLString] placeholderImage:[UIImage imageNamed:@"placeholder-stamp.png"]]; + + self.textLabel.text = spot.name; +} + +#pragma mark - UITableViewCell + +- (void)prepareForReuse { + [self.imageView cancelImageRequestOperation]; + self.textLabel.text = nil; + self.detailTextLabel.text = nil; +} + +#pragma mark - UIView + +//- (void)layoutSubviews { +// [super layoutSubviews]; +// +// CGRect imageViewFrame = self.imageView.frame; +// CGRect textLabelFrame = self.textLabel.frame; +// CGRect detailTextLabelFrame = self.detailTextLabel.frame; +// +// imageViewFrame.origin = CGPointMake(10.0f, 10.0f); +// imageViewFrame.size = CGSizeMake(50.0f, 50.0f); +// +// textLabelFrame.origin.x = imageViewFrame.size.width + 25.0f; +// detailTextLabelFrame.origin.x = textLabelFrame.origin.x; +// +// textLabelFrame.size.width = 240.0f; +// detailTextLabelFrame.size.width = textLabelFrame.size.width; +// +// self.textLabel.frame = textLabelFrame; +// self.detailTextLabel.frame = detailTextLabelFrame; +// self.imageView.frame = CGRectIntegral(imageViewFrame); +//} + @end From 04dad96904a767734ecca3a3fe3859c22a22fe33 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 16 Sep 2011 23:23:14 -0500 Subject: [PATCH 04/41] Fixing zlib inflate and deflate NSData category methods --- AFNetworking/NSData+AFNetworking.m | 133 ++++++++++++++++------------- 1 file changed, 72 insertions(+), 61 deletions(-) diff --git a/AFNetworking/NSData+AFNetworking.m b/AFNetworking/NSData+AFNetworking.m index 13ba284..da43a49 100644 --- a/AFNetworking/NSData+AFNetworking.m +++ b/AFNetworking/NSData+AFNetworking.m @@ -29,65 +29,6 @@ NSString * const AFZlibErrorDomain = @"com.alamofire.networking.zlib.error"; static char Base64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static inline NSUInteger NSDataEstimatedCompressedLength(NSData *data) { - return [data length] / 2; -} - -typedef enum { - GzipDeflate = -1, - GzipInflate = 1, -} GzipOperation; - -@interface NSData (_AFNetworking) -+ (NSData *)dataByTransformingData:(NSData *)data - usingGZipOperation:(GzipOperation)operation - error:(NSError **)error; -@end - -@implementation NSData (_AFNetworking) - -+ (NSData *)dataByTransformingData:(NSData *)data - usingGZipOperation:(GzipOperation)operation - error:(NSError **)error -{ - z_stream zStream; - - NSUInteger estimatedLength = NSDataEstimatedCompressedLength(data); - NSMutableData *mutableData = [NSMutableData dataWithLength:estimatedLength]; - - int status; - zStream.next_in = (Bytef *)[data bytes]; - zStream.avail_in = (unsigned int)[data length]; - zStream.avail_out = 0; - - NSInteger bytesProcessedAlready = zStream.total_out; - while (zStream.avail_out == 0) { - if (zStream.total_out - bytesProcessedAlready >= [mutableData length]) { - [mutableData increaseLengthBy:estimatedLength / 2]; - } - - zStream.next_out = [mutableData mutableBytes] + zStream.total_out-bytesProcessedAlready; - zStream.avail_out = (unsigned int)([mutableData length] - (zStream.total_out-bytesProcessedAlready)); - status = deflate(&zStream, Z_FINISH); - - if (status == Z_STREAM_END) { - break; - } else if (status != Z_OK) { - if (error) { - *error = [NSError errorWithDomain:AFZlibErrorDomain code:status userInfo:nil]; - } - - return nil; - } - } - - [mutableData setLength:zStream.total_out - bytesProcessedAlready]; - - return mutableData; -} - -@end - #pragma mark - @implementation NSData (AFNetworking) @@ -120,11 +61,81 @@ typedef enum { } - (NSData *)dataByGZipCompressingWithError:(NSError **)error { - return [NSData dataByTransformingData:self usingGZipOperation:GzipDeflate error:error]; + if ([self length] == 0) { + return self; + } + + z_stream zStream; + + zStream.zalloc = Z_NULL; + zStream.zfree = Z_NULL; + zStream.opaque = Z_NULL; + zStream.next_in = (Bytef *)[self bytes]; + zStream.avail_in = [self length]; + zStream.total_out = 0; + + if (deflateInit(&zStream, Z_DEFAULT_COMPRESSION) != Z_OK) { + return nil; + } + + NSUInteger compressionChunkSize = 16384; // 16Kb + NSMutableData *compressedData = [NSMutableData dataWithLength:compressionChunkSize]; + + do { + if (zStream.total_out >= [compressedData length]) { + [compressedData increaseLengthBy:compressionChunkSize]; + } + + zStream.next_out = [compressedData mutableBytes] + zStream.total_out; + zStream.avail_out = [compressedData length] - zStream.total_out; + + deflate(&zStream, Z_FINISH); + + } while (zStream.avail_out == 0); + + deflateEnd(&zStream); + [compressedData setLength:zStream.total_out]; + + return [NSData dataWithData:compressedData]; } - (NSData *)dataByGZipDecompressingDataWithError:(NSError **)error { - return [NSData dataByTransformingData:self usingGZipOperation:GzipInflate error:error]; + z_stream zStream; + + zStream.zalloc = Z_NULL; + zStream.zfree = Z_NULL; + zStream.next_in = (Bytef *)[self bytes]; + zStream.avail_in = [self length]; + zStream.avail_out = 0; + zStream.total_out = 0; + + NSUInteger estimatedLength = [self length] / 2; + NSMutableData *decompressedData = [NSMutableData dataWithLength:estimatedLength]; + + do { + if (zStream.total_out >= [decompressedData length]) { + [decompressedData increaseLengthBy:estimatedLength / 2]; + } + + zStream.next_out = [decompressedData mutableBytes] + zStream.total_out; + zStream.avail_out = [decompressedData length] - zStream.total_out; + + int status = inflate(&zStream, Z_FINISH); + + if (status == Z_STREAM_END) { + break; + } else if (status != Z_OK) { + if (error) { + *error = [NSError errorWithDomain:AFZlibErrorDomain code:status userInfo:nil]; + } + + return nil; + } + } while (zStream.avail_out == 0); + + [decompressedData setLength:zStream.total_out]; + + return [NSData dataWithData:decompressedData]; } @end From c74eca7c9b2773e098a0cb33d9c202f2594857f5 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 16 Sep 2011 23:26:03 -0500 Subject: [PATCH 05/41] Updating code example in README (setProgressBlock: -> setUploadProgressBlock:) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9cc95c6..a6c0e82 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ NSDictionary *parameters = [NSDictionary dictionaryWithObject:@"300x300" forKey: AFHTTPRequestOperation *operation = [AFHTTPRequestOperation operationWithRequest:request completion:^(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error) { NSLog(@"Upload Complete"); }]; -[operation setProgressBlock:^(NSUInteger totalBytesWritten, NSUInteger totalBytesExpectedToWrite) { +[operation setUploadProgressBlock:^(NSUInteger totalBytesWritten, NSUInteger totalBytesExpectedToWrite) { NSLog(@"Sent %d of %d bytes", totalBytesWritten, totalBytesExpectedToWrite); }]; From 3e3d94f93828f5eeb11fc1218c3bc45399e9a66e Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 16 Sep 2011 23:57:01 -0500 Subject: [PATCH 06/41] Removing stray reference to QuartzCore.framework --- Example/AFNetworking Example.xcodeproj/project.pbxproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/Example/AFNetworking Example.xcodeproj/project.pbxproj b/Example/AFNetworking Example.xcodeproj/project.pbxproj index 6b71fb1..b61798d 100644 --- a/Example/AFNetworking Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking Example.xcodeproj/project.pbxproj @@ -58,7 +58,6 @@ F874B5D613E0AA6500B28E3E /* AFRestClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = AFRestClient.h; path = ../AFNetworking/AFRestClient.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; F874B5D713E0AA6500B28E3E /* UIImage+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImage+AFNetworking.h"; path = "../AFNetworking/UIImage+AFNetworking.h"; sourceTree = ""; }; F874B5D813E0AA6500B28E3E /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImageView+AFNetworking.h"; path = "../AFNetworking/UIImageView+AFNetworking.h"; sourceTree = ""; }; - F8870C3D1424409800BCD863 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; F8D25D101396A9C400CF3BD6 /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = ""; }; F8D25D111396A9C400CF3BD6 /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = ""; }; F8D25D131396A9C400CF3BD6 /* TTTLocationFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TTTLocationFormatter.h; sourceTree = ""; }; @@ -175,7 +174,6 @@ F8E469551395739C00DB05C8 = { isa = PBXGroup; children = ( - F8870C3D1424409800BCD863 /* QuartzCore.framework */, F8E469B71395759C00DB05C8 /* Networking Extensions */, F8E4696A1395739D00DB05C8 /* Classes */, F8E469ED1395812A00DB05C8 /* Images */, From 5cf1028433228b20e7cf30a463353981809fcd0b Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Fri, 16 Sep 2011 23:57:47 -0500 Subject: [PATCH 07/41] Removing AFRestClient basic forms of GET/POST/PUT/DELETE methods --- AFNetworking/AFRestClient.h | 16 ---------------- AFNetworking/AFRestClient.m | 16 ---------------- 2 files changed, 32 deletions(-) diff --git a/AFNetworking/AFRestClient.h b/AFNetworking/AFRestClient.h index b171815..6011afe 100644 --- a/AFNetworking/AFRestClient.h +++ b/AFNetworking/AFRestClient.h @@ -54,37 +54,21 @@ - (void)cancelAllHTTPOperations; -- (void)getPath:(NSString *)path - parameters:(NSDictionary *)parameters - success:(void (^)(id response))success; - - (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success failure:(void (^)(NSError *error))failure; -- (void)postPath:(NSString *)path - parameters:(NSDictionary *)parameters - success:(void (^)(id response))success; - - (void)postPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success failure:(void (^)(NSError *error))failure; -- (void)putPath:(NSString *)path - parameters:(NSDictionary *)parameters - success:(void (^)(id response))success; - - (void)putPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success failure:(void (^)(NSError *error))failure; -- (void)deletePath:(NSString *)path - parameters:(NSDictionary *)parameters - success:(void (^)(id response))success; - - (void)deletePath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success diff --git a/AFNetworking/AFRestClient.m b/AFNetworking/AFRestClient.m index cd128fb..2f6f731 100644 --- a/AFNetworking/AFRestClient.m +++ b/AFNetworking/AFRestClient.m @@ -155,37 +155,21 @@ static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding #pragma mark - -- (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success { - [self getPath:path parameters:parameters success:success failure:nil]; -} - - (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success failure:(void (^)(NSError *error))failure { NSURLRequest *request = [self requestWithMethod:@"GET" path:path parameters:parameters]; [self enqueueHTTPOperationWithRequest:request success:success failure:failure]; } -- (void)postPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success { - [self postPath:path parameters:parameters success:success failure:nil]; -} - - (void)postPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success failure:(void (^)(NSError *error))failure { NSURLRequest *request = [self requestWithMethod:@"POST" path:path parameters:parameters]; [self enqueueHTTPOperationWithRequest:request success:success failure:failure]; } -- (void)putPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success { - [self putPath:path parameters:parameters success:success failure:nil]; -} - - (void)putPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success failure:(void (^)(NSError *error))failure { NSURLRequest *request = [self requestWithMethod:@"PUT" path:path parameters:parameters]; [self enqueueHTTPOperationWithRequest:request success:success failure:failure]; } -- (void)deletePath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success { - [self deletePath:path parameters:parameters success:success failure:nil]; -} - - (void)deletePath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success failure:(void (^)(NSError *error))failure { NSURLRequest *request = [self requestWithMethod:@"DELETE" path:path parameters:parameters]; [self enqueueHTTPOperationWithRequest:request success:success failure:failure]; From ce2034beb887a72efaac7ba79db1589e3bafce30 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 18 Sep 2011 13:19:18 -0500 Subject: [PATCH 08/41] First draft of documentation for AFHTTPRequestOperation --- AFNetworking/AFHTTPRequestOperation.h | 48 +++++++++++++++++++++++++++ AFNetworking/AFHTTPRequestOperation.m | 8 +++-- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/AFNetworking/AFHTTPRequestOperation.h b/AFNetworking/AFHTTPRequestOperation.h index 4e08bec..4263377 100644 --- a/AFNetworking/AFHTTPRequestOperation.h +++ b/AFNetworking/AFHTTPRequestOperation.h @@ -28,6 +28,9 @@ extern NSString * const AFNetworkingErrorDomain; extern NSString * const AFHTTPOperationDidStartNotification; extern NSString * const AFHTTPOperationDidFinishNotification; +/** + + */ @interface AFHTTPRequestOperation : NSOperation { @private NSSet *_runLoopModes; @@ -52,15 +55,60 @@ extern NSString * const AFHTTPOperationDidFinishNotification; @property (readonly, nonatomic, retain) NSData *responseBody; @property (readonly) NSString *responseString; +///--------------------------------------- +/// @name Creating HTTP Request Operations +///--------------------------------------- + +/** + Creates and returns an `AFHTTPRequestOperation` object and sets the specified completion callback. + + @param urlRequest The request object to be loaded asynchronously during execution of the operation + @param completion A block object to be executed when the HTTP request operation is finished. This block has no return value and takes four arguments: the NSURLRequest sent from the client and the NSHTTPURLResponse received from the server, the NSData received by the server during the execution of the request, and an NSError, which will have been set if an error occured while loading the request. + + @see operationWithRequest:inputStream:outputStream:completion + + @return A new HTTP request operation + */ + (id)operationWithRequest:(NSURLRequest *)urlRequest completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error))completion; +/** + Creates and returns an `AFHTTPRequestOperation` object and sets the specified input and output streams, and completion callback. + + @param urlRequest The request object to be loaded asynchronously during execution of the operation + @param inputStream The input stream object for reading data to be sent during the request. If set, the input stream is set as the HTTPBodyStream on the NSMutableURLRequest, and the request method is changed to `POST`. This argument may be `nil`. + @param outputStream The output stream object for writing data received during the request. If set, data accumulated in NSURLConnectionDelegate methods will be sent to the output stream, and the NSData parameter in the completion block will be `nil`. This argument may be `nil`. + @param completion A block object to be executed when the HTTP request operation is finished. This block has no return value and takes four arguments: the NSURLRequest sent from the client and the NSHTTPURLResponse received from the server, the NSData received by the server during the execution of the request, and an NSError, which will have been set if an error occured while loading the request. This argument may be `NULL`. + + @see operationWithRequest:completion + + @return A new HTTP request operation + */ + (id)operationWithRequest:(NSURLRequest *)urlRequest inputStream:(NSInputStream *)inputStream outputStream:(NSOutputStream *)outputStream completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))completion; +///--------------------------------- +/// @name Setting Progress Callbacks +///--------------------------------- + +/** + Sets a callback to be called when an undetermined number of bytes have been downloaded from the server. + + @param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes two arguments: the total bytes written, and the total bytes expected to be written during the request, as initially determined by the length of the HTTP body. This block may be called multiple times. + + @see setDownloadProgressBlock + */ - (void)setUploadProgressBlock:(void (^)(NSUInteger totalBytesWritten, NSUInteger totalBytesExpectedToWrite))block; + +/** + Sets a callback to be called when an undetermined number of bytes have been uploaded to the server. + + @param block A block object to be called when an undetermined number of bytes have been uploaded to the server. This block has no return value and takes two arguments: the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the NSHTTPURLResponse. This block may be called multiple times. + + @see setUploadProgressBlock + */ - (void)setDownloadProgressBlock:(void (^)(NSUInteger totalBytesRead, NSUInteger totalBytesExpectedToRead))block; @end diff --git a/AFNetworking/AFHTTPRequestOperation.m b/AFNetworking/AFHTTPRequestOperation.m index 3b2775b..8d22647 100644 --- a/AFNetworking/AFHTTPRequestOperation.m +++ b/AFNetworking/AFHTTPRequestOperation.m @@ -149,9 +149,11 @@ static NSThread *_networkRequestThread = nil; completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))completion { NSMutableURLRequest *mutableURLRequest = [[urlRequest mutableCopy] autorelease]; - [mutableURLRequest setHTTPBodyStream:inputStream]; - if ([[mutableURLRequest HTTPMethod] isEqualToString:@"GET"]) { - [mutableURLRequest setHTTPMethod:@"POST"]; + if (inputStream) { + [mutableURLRequest setHTTPBodyStream:inputStream]; + if ([[mutableURLRequest HTTPMethod] isEqualToString:@"GET"]) { + [mutableURLRequest setHTTPMethod:@"POST"]; + } } AFHTTPRequestOperation *operation = [self operationWithRequest:mutableURLRequest completion:^(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error) { From 0f5814b17f0a97efbffd2810aaa567350798ebd6 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 18 Sep 2011 13:56:30 -0500 Subject: [PATCH 09/41] First draft of documentation for AFJSONRequestOperation --- AFNetworking/AFJSONRequestOperation.h | 47 +++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/AFNetworking/AFJSONRequestOperation.h b/AFNetworking/AFJSONRequestOperation.h index bbb482b..4853e5c 100644 --- a/AFNetworking/AFJSONRequestOperation.h +++ b/AFNetworking/AFJSONRequestOperation.h @@ -24,20 +24,67 @@ @interface AFJSONRequestOperation : AFHTTPRequestOperation +/** + Creates and returns an `AFJSONRequestOperation` object and sets the specified success callback. + + @param urlRequest The request object to be loaded asynchronously during execution of the operation + @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable [HTTP content type](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17) (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request, or nil if there was an error. + + @see defaultAcceptableStatusCodes + @see defaultAcceptableContentTypes + @see operationWithRequest:success:failure: + + @return A new JSON request operation + */ + (id)operationWithRequest:(NSURLRequest *)urlRequest success:(void (^)(id JSON))success; +/** + Creates and returns an `AFJSONRequestOperation` object and sets the specified success and failure callbacks. + + @param urlRequest The request object to be loaded asynchronously during execution of the operation + @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable [HTTP content type](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17) (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request. + @param failure A block object to be executed when the JSON request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. + + @see defaultAcceptableStatusCodes + @see defaultAcceptableContentTypes + @see operationWithRequest:success: + + @return A new JSON request operation + */ + (id)operationWithRequest:(NSURLRequest *)urlRequest success:(void (^)(id JSON))success failure:(void (^)(NSError *error))failure; +/** + Creates and returns an `AFJSONRequestOperation` object and sets the specified success and failure callbacks, as well as the status codes and content types that are acceptable for a successful request. + + @param urlRequest The request object to be loaded asynchronously during execution of the operation + @param acceptableStatusCodes An `NSIndexSet` object that specifies the ranges of acceptable [HTTP status codes](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html). If you specify nil, all status codes will be considered acceptable. + @param acceptableContentTypes An `NSSet` object that specifies the acceptable [HTTP content types](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17). If you specify nil, all content types will be considered acceptable. + @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable [HTTP content type](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17) (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request. + @param failure A block object to be executed when the JSON request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. + + @return A new JSON request operation + */ + (id)operationWithRequest:(NSURLRequest *)urlRequest acceptableStatusCodes:(NSIndexSet *)acceptableStatusCodes acceptableContentTypes:(NSSet *)acceptableContentTypes success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; +/** + Returns an `NSIndexSet` object containing the ranges of acceptable [HTTP status codes](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) used in operationWithRequest:success and operationWithRequest:success:failure. + + By default, this is the range 200 to 299, inclusive. + */ + (NSIndexSet *)defaultAcceptableStatusCodes; + +/** + Returns an `NSSet` object containing the acceptable [HTTP content type](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17) used in operationWithRequest:success and operationWithRequest:success:failure. + + By default, this contains `application/json`, `application/x-javascript`, `text/javascript`, `text/x-javascript`, `text/x-json`, `text/json`, and `text/plain` + */ + (NSSet *)defaultAcceptableContentTypes; @end From e2a00952aa30dfc60e3c821261abddfe7c5fc2ca Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 18 Sep 2011 14:06:22 -0500 Subject: [PATCH 10/41] Revising AFJSONRequestOperation documentation When nil is specified as acceptable status code or content type, don't perform those validations (i.e. accept any value) --- AFNetworking/AFJSONRequestOperation.h | 19 ++++++++++++++----- AFNetworking/AFJSONRequestOperation.m | 4 ++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/AFNetworking/AFJSONRequestOperation.h b/AFNetworking/AFJSONRequestOperation.h index 4853e5c..be2d3bd 100644 --- a/AFNetworking/AFJSONRequestOperation.h +++ b/AFNetworking/AFJSONRequestOperation.h @@ -24,11 +24,15 @@ @interface AFJSONRequestOperation : AFHTTPRequestOperation +///--------------------------------------- +/// @name Creating JSON Request Operations +///--------------------------------------- + /** Creates and returns an `AFJSONRequestOperation` object and sets the specified success callback. @param urlRequest The request object to be loaded asynchronously during execution of the operation - @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable [HTTP content type](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17) (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request, or nil if there was an error. + @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request, or nil if there was an error. @see defaultAcceptableStatusCodes @see defaultAcceptableContentTypes @@ -43,7 +47,7 @@ Creates and returns an `AFJSONRequestOperation` object and sets the specified success and failure callbacks. @param urlRequest The request object to be loaded asynchronously during execution of the operation - @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable [HTTP content type](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17) (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request. + @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request. @param failure A block object to be executed when the JSON request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. @see defaultAcceptableStatusCodes @@ -60,9 +64,9 @@ Creates and returns an `AFJSONRequestOperation` object and sets the specified success and failure callbacks, as well as the status codes and content types that are acceptable for a successful request. @param urlRequest The request object to be loaded asynchronously during execution of the operation - @param acceptableStatusCodes An `NSIndexSet` object that specifies the ranges of acceptable [HTTP status codes](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html). If you specify nil, all status codes will be considered acceptable. - @param acceptableContentTypes An `NSSet` object that specifies the acceptable [HTTP content types](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17). If you specify nil, all content types will be considered acceptable. - @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable [HTTP content type](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17) (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request. + @param acceptableStatusCodes An `NSIndexSet` object that specifies the ranges of acceptable status codes. If you specify nil, all status codes will be considered acceptable. + @param acceptableContentTypes An `NSSet` object that specifies the acceptable content types. If you specify nil, all content types will be considered acceptable. + @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request. @param failure A block object to be executed when the JSON request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. @return A new JSON request operation @@ -73,6 +77,11 @@ success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; + +///---------------------------------- +/// @name Getting Default HTTP Values +///---------------------------------- + /** Returns an `NSIndexSet` object containing the ranges of acceptable [HTTP status codes](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) used in operationWithRequest:success and operationWithRequest:success:failure. diff --git a/AFNetworking/AFJSONRequestOperation.m b/AFNetworking/AFJSONRequestOperation.m index 0baabd8..3f6b3bf 100644 --- a/AFNetworking/AFJSONRequestOperation.m +++ b/AFNetworking/AFJSONRequestOperation.m @@ -65,7 +65,7 @@ static dispatch_queue_t json_request_operation_processing_queue() { { return [self operationWithRequest:urlRequest completion:^(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error) { if (!error) { - if (![acceptableStatusCodes containsIndex:[response statusCode]]) { + if (acceptableStatusCodes && ![acceptableStatusCodes containsIndex:[response statusCode]]) { NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; [userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected status code %@, got %d", nil), acceptableStatusCodes, [response statusCode]] forKey:NSLocalizedDescriptionKey]; [userInfo setValue:[request URL] forKey:NSURLErrorFailingURLErrorKey]; @@ -73,7 +73,7 @@ static dispatch_queue_t json_request_operation_processing_queue() { error = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo] autorelease]; } - if (![acceptableContentTypes containsObject:[response MIMEType]]) { + if (acceptableContentTypes && ![acceptableContentTypes containsObject:[response MIMEType]]) { NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; [userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected content type %@, got %@", nil), acceptableContentTypes, [response MIMEType]] forKey:NSLocalizedDescriptionKey]; [userInfo setValue:[request URL] forKey:NSURLErrorFailingURLErrorKey]; From 0a5e5400ccc4976649aceae132b3e1af3d8eee22 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 18 Sep 2011 14:09:01 -0500 Subject: [PATCH 11/41] Revising link formatting in AFJSONRequestOperation documentation --- AFNetworking/AFJSONRequestOperation.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFJSONRequestOperation.h b/AFNetworking/AFJSONRequestOperation.h index be2d3bd..4d1a147 100644 --- a/AFNetworking/AFJSONRequestOperation.h +++ b/AFNetworking/AFJSONRequestOperation.h @@ -83,14 +83,14 @@ ///---------------------------------- /** - Returns an `NSIndexSet` object containing the ranges of acceptable [HTTP status codes](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) used in operationWithRequest:success and operationWithRequest:success:failure. + Returns an `NSIndexSet` object containing the ranges of acceptable HTTP status codes (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) used in operationWithRequest:success and operationWithRequest:success:failure. By default, this is the range 200 to 299, inclusive. */ + (NSIndexSet *)defaultAcceptableStatusCodes; /** - Returns an `NSSet` object containing the acceptable [HTTP content type](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17) used in operationWithRequest:success and operationWithRequest:success:failure. + Returns an `NSSet` object containing the acceptable HTTP content type (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17) used in operationWithRequest:success and operationWithRequest:success:failure. By default, this contains `application/json`, `application/x-javascript`, `text/javascript`, `text/x-javascript`, `text/x-json`, `text/json`, and `text/plain` */ From 5755666b3098f682cff34cb8b200399693627c2f Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 18 Sep 2011 14:27:32 -0500 Subject: [PATCH 12/41] Adding class overview to AFHTTPRequestOperation documentation --- AFNetworking/AFHTTPRequestOperation.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/AFNetworking/AFHTTPRequestOperation.h b/AFNetworking/AFHTTPRequestOperation.h index 4263377..532323d 100644 --- a/AFNetworking/AFHTTPRequestOperation.h +++ b/AFNetworking/AFHTTPRequestOperation.h @@ -29,7 +29,20 @@ extern NSString * const AFHTTPOperationDidStartNotification; extern NSString * const AFHTTPOperationDidFinishNotification; /** - + `AFHTTPRequestOperation` is an `NSOperation` that implements the `NSURLConnection` delegate methods, and provides a simple block-based interface to asynchronously get the result and context of that operation finishes. + + # Subclassing Notes + + In cases where you don't need all of the information provided in the callback, or you want to validate and/or represent it in a different way, it makes sense to create a subclass to define this behavior. + + For instance, `AFJSONRequestOperation` makes a distinction between successful and unsuccessful requests by validating the HTTP status code and content type of the response, and provides separate callbacks for both the succeeding and failing cases. As another example, `AFImageRequestOperation` offers a pared-down callback, with a single block argument that is an image object that was created from the response data. + + ## Methods to subclass + + Unless you need to override specific `NSURLConnection` delegate methods, you shouldn't need to subclass any methods. Instead, you should provide alternative constructor class methods, that are essentially wrappers around the callback from `AFHTTPRequestOperation`. + + @see NSOperation + @see NSURLConnection */ @interface AFHTTPRequestOperation : NSOperation { @private From 2f7f527d9cc6f88733cb736d71113cfdb42747cb Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 18 Sep 2011 15:06:29 -0500 Subject: [PATCH 13/41] First (half of a) draft of AFRestClient documentation --- AFNetworking/AFRestClient.h | 74 +++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/AFNetworking/AFRestClient.h b/AFNetworking/AFRestClient.h index 6011afe..747d026 100644 --- a/AFNetworking/AFRestClient.h +++ b/AFNetworking/AFRestClient.h @@ -33,27 +33,101 @@ NSOperationQueue *_operationQueue; } +/** + An `NSURL` object that is used as the base for paths specified in methods such as `getPath:parameteres:success:failure` + */ +@property (readonly, nonatomic, retain) NSURL *baseURL; + +///-------------------------------- +/// @name Initializing REST Clients +///-------------------------------- + +/** + Initializes an `AFRestClient` object with the specified base URL. + + @param url The base URL for the REST client. This argument must not be nil. + + @return The newly-initialized REST client + */ - (id)initWithBaseURL:(NSURL *)url; +///---------------------------------- +/// @name Managing HTTP Header Values +///---------------------------------- + +/** + Returns the value for the HTTP headers set in request objects created by the REST client + + @param header The HTTP header to return the default value for + + @return The default value for the HTTP header, or `nil` if unspecified + */ - (NSString *)defaultValueForHeader:(NSString *)header; + +/** + Sets the value for the HTTP headers set in request objects made by the REST client. If `nil`, removes the existing value for that header. + + @param header The HTTP header to set a default value for + @param value The value set as default for the specified header, or `nil + */ - (void)setDefaultHeader:(NSString *)header value:(NSString *)value; + +/** + Sets the "Authorization" HTTP header set in request objects made by the REST client to a basic authentication value with Base64-encoded username and password. This overwrites any existing value for this header. + + @param username The HTTP basic auth username + @param password The HTTP basic auth password + */ - (void)setAuthorizationHeaderWithUsername:(NSString *)username password:(NSString *)password; + +/** + Sets the "Authorization" HTTP header set in request objects made by the REST client to a token-based authentication value, such as an OAuth access token. This overwrites any existing value for this header. + + @param token The authentication token + */ - (void)setAuthorizationHeaderWithToken:(NSString *)token; + +/** + Clears any existing value for the "Authorization" HTTP header. + */ - (void)clearAuthorizationHeader; +///------------------------------- +/// @name Creating Request Objects +///------------------------------- + +/** + Creates an `NSMutableURLRequest` object with the specified HTTP method, resource path, and parameters, with the default HTTP headers specified for the client. + + @param method The HTTP method for the request, such as `GET`, `POST`, `PUT`, or `DELETE` + @param path The resource path to be appended to the REST client's base URL and used as the request URL + @param parameters The parameters to be either set as a query string for `GET` requests, or form URL-encoded and set in the request HTTP body + + @return An `NSMutableURLRequest` object + */ - (NSMutableURLRequest *)requestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters; +///-------------------------------- +/// @name Enqueuing HTTP Operations +///-------------------------------- - (void)enqueueHTTPOperation:(AFHTTPRequestOperation *)operation; - (void)enqueueHTTPOperationWithRequest:(NSURLRequest *)request success:(void (^)(id response))success failure:(void (^)(NSError *error))failure; +///--------------------------------- +/// @name Cancelling HTTP Operations +///--------------------------------- + - (void)cancelHTTPOperationsWithRequest:(NSURLRequest *)request; - (void)cancelAllHTTPOperations; +///--------------------------- +/// @name Making HTTP Requests +///--------------------------- - (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success From ca02e02b1164cfb884f3e313264034ddaaf7634d Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 11:36:39 -0500 Subject: [PATCH 14/41] Removing categories on NSData and NSString, moving them to static functions in AFRestClient Removing Gzip functionality, which will be extracted into its own library --- AFNetworking/AFRestClient.h | 6 +- AFNetworking/AFRestClient.m | 53 +++++-- AFNetworking/NSData+AFNetworking.h | 33 ---- AFNetworking/NSData+AFNetworking.m | 141 ------------------ AFNetworking/NSString+AFNetworking.h | 30 ---- AFNetworking/NSString+AFNetworking.m | 38 ----- .../project.pbxproj | 12 -- 7 files changed, 48 insertions(+), 265 deletions(-) delete mode 100644 AFNetworking/NSData+AFNetworking.h delete mode 100644 AFNetworking/NSData+AFNetworking.m delete mode 100644 AFNetworking/NSString+AFNetworking.h delete mode 100644 AFNetworking/NSString+AFNetworking.m diff --git a/AFNetworking/AFRestClient.h b/AFNetworking/AFRestClient.h index 747d026..0b4ac17 100644 --- a/AFNetworking/AFRestClient.h +++ b/AFNetworking/AFRestClient.h @@ -24,11 +24,11 @@ #import "AFHTTPRequestOperation.h" #import "NSMutableURLRequest+AFNetworking.h" -#import "NSString+AFNetworking.h" @interface AFRestClient : NSObject { @private NSURL *_baseURL; + NSStringEncoding _stringEncoding; NSMutableDictionary *_defaultHeaders; NSOperationQueue *_operationQueue; } @@ -38,6 +38,10 @@ */ @property (readonly, nonatomic, retain) NSURL *baseURL; +@property (nonatomic, assign) NSStringEncoding stringEncoding; + +@property (readonly, nonatomic, retain) NSOperationQueue *operationQueue;; + ///-------------------------------- /// @name Initializing REST Clients ///-------------------------------- diff --git a/AFNetworking/AFRestClient.m b/AFNetworking/AFRestClient.m index 2f6f731..ff72495 100644 --- a/AFNetworking/AFRestClient.m +++ b/AFNetworking/AFRestClient.m @@ -23,9 +23,40 @@ #import "AFRestClient.h" #import "AFJSONRequestOperation.h" -#import "NSData+AFNetworking.h" +static NSString * AFBase64EncodedStringFromString(NSString *string) { + NSData *data = [NSData dataWithBytes:[string UTF8String] length:[string length]]; + NSUInteger length = [data length]; + NSMutableData *mutableData = [NSMutableData dataWithLength:((length + 2) / 3) * 4]; + + uint8_t *input = (uint8_t *)[data bytes]; + uint8_t *output = (uint8_t *)[mutableData mutableBytes]; + + for (NSUInteger i = 0; i < length; i += 3) { + NSUInteger value = 0; + for (NSUInteger j = i; j < (i + 3); j++) { + value <<= 8; + if (j < length) { + value |= (0xFF & input[j]); + } + } + + static char const kAFBase64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding; + NSInteger idx = (i / 3) * 4; + output[idx + 0] = kAFBase64EncodingTable[(value >> 18) & 0x3F]; + output[idx + 1] = kAFBase64EncodingTable[(value >> 12) & 0x3F]; + output[idx + 2] = (i + 1) < length ? kAFBase64EncodingTable[(value >> 6) & 0x3F] : '='; + output[idx + 3] = (i + 2) < length ? kAFBase64EncodingTable[(value >> 0) & 0x3F] : '='; + } + + return [[[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding] autorelease]; +} + +static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSStringEncoding encoding) { + static NSString * const kAFLegalCharactersToBeEscaped = @"?!@#$^&%*+,:;='\"`<>()[]{}/\\|~ "; + + return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, (CFStringRef)kAFLegalCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding)) autorelease]; +} @interface AFRestClient () @property (readwrite, nonatomic, retain) NSURL *baseURL; @@ -35,6 +66,7 @@ static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding @implementation AFRestClient @synthesize baseURL = _baseURL; +@synthesize stringEncoding = _stringEncoding; @synthesize defaultHeaders = _defaultHeaders; @synthesize operationQueue = _operationQueue; @@ -46,8 +78,7 @@ static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding self.baseURL = url; - self.operationQueue = [[[NSOperationQueue alloc] init] autorelease]; - [self.operationQueue setMaxConcurrentOperationCount:2]; + self.stringEncoding = NSUTF8StringEncoding; self.defaultHeaders = [NSMutableDictionary dictionary]; @@ -64,6 +95,9 @@ static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43 [self setDefaultHeader:@"User-Agent" value:[NSString stringWithFormat:@"%@/%@ (%@, %@ %@, %@, Scale/%f)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey], @"unknown", [[UIDevice currentDevice] systemName], [[UIDevice currentDevice] systemVersion], [[UIDevice currentDevice] model], ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] ? [[UIScreen mainScreen] scale] : 1.0)]]; + self.operationQueue = [[[NSOperationQueue alloc] init] autorelease]; + [self.operationQueue setMaxConcurrentOperationCount:2]; + return self; } @@ -83,9 +117,8 @@ static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding } - (void)setAuthorizationHeaderWithUsername:(NSString *)username password:(NSString *)password { - NSString *authHeader = [NSString stringWithFormat:@"%@:%@", username, password]; - NSString *encodedAuthHeader = [[NSData dataWithBytes:[authHeader UTF8String] length:[authHeader length]] base64EncodedString]; - [self setDefaultHeader:@"Authorization" value:[NSString stringWithFormat:@"Basic %@", encodedAuthHeader]]; + NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", username, password]; + [self setDefaultHeader:@"Authorization" value:[NSString stringWithFormat:@"Basic %@", AFBase64EncodedStringFromString(basicAuthCredentials)]]; } - (void)setAuthorizationHeaderWithToken:(NSString *)token { @@ -106,7 +139,7 @@ static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding if (parameters) { NSMutableArray *mutableParameterComponents = [NSMutableArray array]; for (id key in [parameters allKeys]) { - NSString *component = [NSString stringWithFormat:@"%@=%@", [[key description] urlEncodedStringWithEncoding:kAFRestClientStringEncoding], [[[parameters valueForKey:key] description] urlEncodedStringWithEncoding:kAFRestClientStringEncoding]]; + NSString *component = [NSString stringWithFormat:@"%@=%@", AFURLEncodedStringFromStringWithEncoding([key description], self.stringEncoding), AFURLEncodedStringFromStringWithEncoding([[parameters valueForKey:key] description], self.stringEncoding)]; [mutableParameterComponents addObject:component]; } NSString *queryString = [mutableParameterComponents componentsJoinedByString:@"&"]; @@ -114,9 +147,9 @@ static NSStringEncoding const kAFRestClientStringEncoding = NSUTF8StringEncoding if ([method isEqualToString:@"GET"]) { url = [NSURL URLWithString:[[url absoluteString] stringByAppendingFormat:[path rangeOfString:@"?"].location == NSNotFound ? @"?%@" : @"&%@", queryString]]; } else { - NSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(kAFRestClientStringEncoding)); + NSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(self.stringEncoding)); [headers setObject:[NSString stringWithFormat:@"application/x-www-form-urlencoded; charset=%@", charset] forKey:@"Content-Type"]; - [request setHTTPBody:[queryString dataUsingEncoding:NSUTF8StringEncoding]]; + [request setHTTPBody:[queryString dataUsingEncoding:self.stringEncoding]]; } } diff --git a/AFNetworking/NSData+AFNetworking.h b/AFNetworking/NSData+AFNetworking.h deleted file mode 100644 index 36e0fbe..0000000 --- a/AFNetworking/NSData+AFNetworking.h +++ /dev/null @@ -1,33 +0,0 @@ -// NSData+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 - -extern NSString * const AFZlibErrorDomain; - -@interface NSData (AFNetworking) - -- (NSString *)base64EncodedString; -- (NSData *)dataByGZipCompressingWithError:(NSError **)error; -- (NSData *)dataByGZipDecompressingDataWithError:(NSError **)error; - -@end diff --git a/AFNetworking/NSData+AFNetworking.m b/AFNetworking/NSData+AFNetworking.m deleted file mode 100644 index da43a49..0000000 --- a/AFNetworking/NSData+AFNetworking.m +++ /dev/null @@ -1,141 +0,0 @@ -// NSData+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 "NSData+AFNetworking.h" -#import "AFHTTPRequestOperation.h" - -#import - -NSString * const AFZlibErrorDomain = @"com.alamofire.networking.zlib.error"; - -static char Base64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -#pragma mark - - -@implementation NSData (AFNetworking) - -- (NSString *)base64EncodedString { - NSUInteger length = [self length]; - NSMutableData *mutableData = [NSMutableData dataWithLength:((length + 2) / 3) * 4]; - - uint8_t *input = (uint8_t *)[self bytes]; - uint8_t *output = (uint8_t *)[mutableData mutableBytes]; - - for (NSUInteger i = 0; i < length; i += 3) { - NSUInteger value = 0; - for (NSUInteger j = i; j < (i + 3); j++) { - value <<= 8; - - if (j < length) { - value |= (0xFF & input[j]); - } - } - - NSInteger idx = (i / 3) * 4; - output[idx + 0] = Base64EncodingTable[(value >> 18) & 0x3F]; - output[idx + 1] = Base64EncodingTable[(value >> 12) & 0x3F]; - output[idx + 2] = (i + 1) < length ? Base64EncodingTable[(value >> 6) & 0x3F] : '='; - output[idx + 3] = (i + 2) < length ? Base64EncodingTable[(value >> 0) & 0x3F] : '='; - } - - return [[[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding] autorelease]; -} - -- (NSData *)dataByGZipCompressingWithError:(NSError **)error { - if ([self length] == 0) { - return self; - } - - z_stream zStream; - - zStream.zalloc = Z_NULL; - zStream.zfree = Z_NULL; - zStream.opaque = Z_NULL; - zStream.next_in = (Bytef *)[self bytes]; - zStream.avail_in = [self length]; - zStream.total_out = 0; - - if (deflateInit(&zStream, Z_DEFAULT_COMPRESSION) != Z_OK) { - return nil; - } - - NSUInteger compressionChunkSize = 16384; // 16Kb - NSMutableData *compressedData = [NSMutableData dataWithLength:compressionChunkSize]; - - do { - if (zStream.total_out >= [compressedData length]) { - [compressedData increaseLengthBy:compressionChunkSize]; - } - - zStream.next_out = [compressedData mutableBytes] + zStream.total_out; - zStream.avail_out = [compressedData length] - zStream.total_out; - - deflate(&zStream, Z_FINISH); - - } while (zStream.avail_out == 0); - - deflateEnd(&zStream); - [compressedData setLength:zStream.total_out]; - - return [NSData dataWithData:compressedData]; -} - -- (NSData *)dataByGZipDecompressingDataWithError:(NSError **)error { - z_stream zStream; - - zStream.zalloc = Z_NULL; - zStream.zfree = Z_NULL; - zStream.next_in = (Bytef *)[self bytes]; - zStream.avail_in = [self length]; - zStream.avail_out = 0; - zStream.total_out = 0; - - NSUInteger estimatedLength = [self length] / 2; - NSMutableData *decompressedData = [NSMutableData dataWithLength:estimatedLength]; - - do { - if (zStream.total_out >= [decompressedData length]) { - [decompressedData increaseLengthBy:estimatedLength / 2]; - } - - zStream.next_out = [decompressedData mutableBytes] + zStream.total_out; - zStream.avail_out = [decompressedData length] - zStream.total_out; - - int status = inflate(&zStream, Z_FINISH); - - if (status == Z_STREAM_END) { - break; - } else if (status != Z_OK) { - if (error) { - *error = [NSError errorWithDomain:AFZlibErrorDomain code:status userInfo:nil]; - } - - return nil; - } - } while (zStream.avail_out == 0); - - [decompressedData setLength:zStream.total_out]; - - return [NSData dataWithData:decompressedData]; -} - -@end diff --git a/AFNetworking/NSString+AFNetworking.h b/AFNetworking/NSString+AFNetworking.h deleted file mode 100644 index 1d94f1b..0000000 --- a/AFNetworking/NSString+AFNetworking.h +++ /dev/null @@ -1,30 +0,0 @@ -// NSString+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 - -@interface NSString (AFNetworking) - -- (NSString *)urlEncodedString; -- (NSString *)urlEncodedStringWithEncoding:(NSStringEncoding)encoding; - -@end diff --git a/AFNetworking/NSString+AFNetworking.m b/AFNetworking/NSString+AFNetworking.m deleted file mode 100644 index 7df406d..0000000 --- a/AFNetworking/NSString+AFNetworking.m +++ /dev/null @@ -1,38 +0,0 @@ -// NSString+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 "NSString+AFNetworking.h" - -@implementation NSString (AFNetworking) - -- (NSString*)urlEncodedString { - return [self urlEncodedStringWithEncoding:NSUTF8StringEncoding]; -} - -// See http://github.com/pokeb/asi-http-request/raw/master/Classes/ASIFormDataRequest.m -- (NSString *)urlEncodedStringWithEncoding:(NSStringEncoding)encoding { - NSString *urlEncodedString = [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, NULL, (CFStringRef)@":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`", CFStringConvertNSStringEncodingToEncoding(encoding)) autorelease]; - - return urlEncodedString ? urlEncodedString : @""; -} - -@end diff --git a/Example/AFNetworking Example.xcodeproj/project.pbxproj b/Example/AFNetworking Example.xcodeproj/project.pbxproj index b61798d..08cc028 100644 --- a/Example/AFNetworking Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking Example.xcodeproj/project.pbxproj @@ -7,9 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - F85CE2D413EC478F00BFAE01 /* NSString+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F85CE2D313EC478F00BFAE01 /* NSString+AFNetworking.m */; }; F85CE2DC13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F85CE2DB13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m */; }; - F85CE55513EC759200BFAE01 /* NSData+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F85CE55413EC759200BFAE01 /* NSData+AFNetworking.m */; }; F874B5D913E0AA6500B28E3E /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */; }; F874B5DA13E0AA6500B28E3E /* AFImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CA13E0AA6500B28E3E /* AFImageCache.m */; }; F874B5DB13E0AA6500B28E3E /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */; }; @@ -36,12 +34,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - F85CE2D213EC478F00BFAE01 /* NSString+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSString+AFNetworking.h"; path = "../AFNetworking/NSString+AFNetworking.h"; sourceTree = ""; }; - F85CE2D313EC478F00BFAE01 /* NSString+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+AFNetworking.m"; path = "../AFNetworking/NSString+AFNetworking.m"; sourceTree = ""; }; F85CE2DA13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSMutableURLRequest+AFNetworking.h"; path = "../AFNetworking/NSMutableURLRequest+AFNetworking.h"; sourceTree = ""; }; F85CE2DB13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSMutableURLRequest+AFNetworking.m"; path = "../AFNetworking/NSMutableURLRequest+AFNetworking.m"; sourceTree = ""; }; - F85CE55313EC759100BFAE01 /* NSData+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSData+AFNetworking.h"; path = "../AFNetworking/NSData+AFNetworking.h"; sourceTree = ""; }; - F85CE55413EC759200BFAE01 /* NSData+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSData+AFNetworking.m"; path = "../AFNetworking/NSData+AFNetworking.m"; sourceTree = ""; }; F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFHTTPRequestOperation.m; path = ../AFNetworking/AFHTTPRequestOperation.m; sourceTree = ""; }; F874B5CA13E0AA6500B28E3E /* AFImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageCache.m; path = ../AFNetworking/AFImageCache.m; sourceTree = ""; }; F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageRequestOperation.m; path = ../AFNetworking/AFImageRequestOperation.m; sourceTree = ""; }; @@ -109,14 +103,10 @@ children = ( F85CE2DA13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.h */, F85CE2DB13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m */, - F85CE2D213EC478F00BFAE01 /* NSString+AFNetworking.h */, - F85CE2D313EC478F00BFAE01 /* NSString+AFNetworking.m */, F874B5D713E0AA6500B28E3E /* UIImage+AFNetworking.h */, F874B5CF13E0AA6500B28E3E /* UIImage+AFNetworking.m */, F874B5D813E0AA6500B28E3E /* UIImageView+AFNetworking.h */, F874B5D013E0AA6500B28E3E /* UIImageView+AFNetworking.m */, - F85CE55313EC759100BFAE01 /* NSData+AFNetworking.h */, - F85CE55413EC759200BFAE01 /* NSData+AFNetworking.m */, ); name = Categories; sourceTree = ""; @@ -358,9 +348,7 @@ F874B5DE13E0AA6500B28E3E /* AFRestClient.m in Sources */, F874B5DF13E0AA6500B28E3E /* UIImage+AFNetworking.m in Sources */, F874B5E013E0AA6500B28E3E /* UIImageView+AFNetworking.m in Sources */, - F85CE2D413EC478F00BFAE01 /* NSString+AFNetworking.m in Sources */, F85CE2DC13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m in Sources */, - F85CE55513EC759200BFAE01 /* NSData+AFNetworking.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 8b8605185b86eebd0f202bee9ffb12decf47d053 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 14:00:05 -0500 Subject: [PATCH 15/41] Replacing NSMutableURLRequest category method with more flexible constructor in AFRestClient Adding AFRestClient -multipartFormRequestWithMethod:path:parameters:constructingBodyWithBlock: Defining AFMultipartFormDataProxy protocol Replacing constant value for string encoding with @property with default of NSUTF8Encoding --- AFNetworking/AFRestClient.h | 24 ++- AFNetworking/AFRestClient.m | 138 ++++++++++++++++++ .../NSMutableURLRequest+AFNetworking.h | 33 ----- .../NSMutableURLRequest+AFNetworking.m | 76 ---------- .../project.pbxproj | 6 - 5 files changed, 158 insertions(+), 119 deletions(-) delete mode 100644 AFNetworking/NSMutableURLRequest+AFNetworking.h delete mode 100644 AFNetworking/NSMutableURLRequest+AFNetworking.m diff --git a/AFNetworking/AFRestClient.h b/AFNetworking/AFRestClient.h index 0b4ac17..f420292 100644 --- a/AFNetworking/AFRestClient.h +++ b/AFNetworking/AFRestClient.h @@ -23,7 +23,7 @@ #import #import "AFHTTPRequestOperation.h" -#import "NSMutableURLRequest+AFNetworking.h" +@protocol AFMultipartFormDataProxy; @interface AFRestClient : NSObject { @private @@ -112,6 +112,12 @@ - (NSMutableURLRequest *)requestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters; +- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method + path:(NSString *)path + parameters:(NSDictionary *)parameters + constructingBodyWithBlock:(void (^)(id formData))block; + + ///-------------------------------- /// @name Enqueuing HTTP Operations ///-------------------------------- @@ -132,9 +138,9 @@ ///--------------------------- /// @name Making HTTP Requests ///--------------------------- -- (void)getPath:(NSString *)path - parameters:(NSDictionary *)parameters - success:(void (^)(id response))success +- (void)getPath:(NSString *)path + parameters:(NSDictionary *)parameters + success:(void (^)(id response))success failure:(void (^)(NSError *error))failure; - (void)postPath:(NSString *)path @@ -152,3 +158,13 @@ success:(void (^)(id response))success failure:(void (^)(NSError *error))failure; @end + +#pragma mark - + +@protocol AFMultipartFormDataProxy +- (void)appendPartWithHeaders:(NSDictionary *)headers body:(NSData *)body; +- (void)appendPartWithFormData:(NSData *)data name:(NSString *)name; +- (void)appendPartWithFile:(NSURL *)fileURL fileName:(NSString *)fileNameOrNil; +- (void)appendData:(NSData *)data; +- (void)appendString:(NSString *)string; +@end diff --git a/AFNetworking/AFRestClient.m b/AFNetworking/AFRestClient.m index ff72495..210aa9d 100644 --- a/AFNetworking/AFRestClient.m +++ b/AFNetworking/AFRestClient.m @@ -23,6 +23,31 @@ #import "AFRestClient.h" #import "AFJSONRequestOperation.h" +static NSString * const kAFMultipartFormLineDelimiter = @"\r\n"; // CRLF +static NSString * const kAFMultipartFormBoundary = @"Boundary+0xAbCdEfGbOuNdArY"; + +static NSString * AFMultipartFormEncapsulationBoundary() { + return [NSString stringWithFormat:@"--%@", kAFMultipartFormBoundary]; +} + +static NSString * AFMultipartFormFinalBoundary() { + return [NSString stringWithFormat:@"--%@--", kAFMultipartFormBoundary]; +} + +@interface AFMutableMultipartFormData : NSObject { +@private + NSStringEncoding _stringEncoding; + NSMutableArray *_lines; +} + +- (id)initWithStringEncoding:(NSStringEncoding)encoding; + +- (NSData *)data; + +@end + +#pragma mark - + static NSString * AFBase64EncodedStringFromString(NSString *string) { NSData *data = [NSData dataWithBytes:[string UTF8String] length:[string length]]; NSUInteger length = [data length]; @@ -161,6 +186,42 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS return request; } +- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method + path:(NSString *)path + parameters:(NSDictionary *)parameters + constructingBodyWithBlock:(void (^)(id formData))block +{ + if (!([method isEqualToString:@"POST"] || [method isEqualToString:@"PUT"] || [method isEqualToString:@"DELETE"])) { + [NSException raise:@"Invalid HTTP Method" format:@"%@ is not supported for multipart form requests; must be either POST, PUT, or DELETE", method]; + return nil; + } + + NSMutableURLRequest *request = [self requestWithMethod:method path:path parameters:nil]; + __block AFMutableMultipartFormData *formData = [[AFMutableMultipartFormData alloc] init]; + + id key = nil; + NSEnumerator *enumerator = [parameters keyEnumerator]; + while ((key = [enumerator nextObject])) { + id value = [parameters valueForKey:key]; + if (![value isKindOfClass:[NSData class]]) { + value = [value description]; + } + + [formData appendPartWithFormData:[value dataUsingEncoding:self.stringEncoding] name:[key description]]; + } + + if (block) { + block(formData); + } + + [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", kAFMultipartFormBoundary] forHTTPHeaderField:@"Content-Type"]; + [request setHTTPBody:[formData data]]; + + [formData autorelease]; + + return request; +} + - (void)enqueueHTTPOperation:(AFHTTPRequestOperation *)operation { [self.operationQueue addOperation:operation]; } @@ -209,3 +270,80 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS } @end + +#pragma mark - + +// multipart/form-data; see http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.2 +@interface AFMutableMultipartFormData () +@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding; +@property (readwrite, nonatomic, retain) NSMutableArray *lines; + +- (void)appendBlankLine; +@end + +@implementation AFMutableMultipartFormData +@synthesize stringEncoding = _stringEncoding; +@synthesize lines = _lines; + +- (id)initWithStringEncoding:(NSStringEncoding)encoding { + self = [super init]; + if (!self) { + return nil; + } + + self.stringEncoding = encoding; + self.lines = [NSMutableArray array]; + + return self; +} + +- (void)dealloc { + [_lines release]; + [super dealloc]; +} + +- (NSData *)data { + NSLog(@"DATA: %@", [[self.lines componentsJoinedByString:kAFMultipartFormLineDelimiter] stringByAppendingString:AFMultipartFormFinalBoundary()]); + + return [[[[self.lines componentsJoinedByString:kAFMultipartFormLineDelimiter] stringByAppendingString:AFMultipartFormFinalBoundary()] stringByAppendingString:kAFMultipartFormLineDelimiter] dataUsingEncoding:self.stringEncoding]; +} + +#pragma mark - AFMultipartFormDataProxy + +- (void)appendPartWithHeaders:(NSDictionary *)headers body:(NSData *)body { + for (NSString *field in [headers allKeys]) { + [self appendString:[NSString stringWithFormat:@"%@: %@", field, [headers valueForKey:field]]]; + } + + [self appendBlankLine]; + [self appendData:body]; +} + +- (void)appendPartWithFormData:(NSData *)data name:(NSString *)name { + [self appendPartWithHeaders:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"form-data; name=\"%@\"", name] forKey:@"Content-Disposition"] body:data]; +} + +- (void)appendPartWithFile:(NSURL *)fileURL fileName:(NSString *)fileNameOrNil { + if (![fileURL isFileURL]) { + [NSException raise:@"Invalid fileURL value" format:@"%@ must be a valid file URL", fileURL]; + return; + } + + NSData *data = [NSData dataWithContentsOfFile:[fileURL absoluteString]]; + NSString *fileName = fileNameOrNil ? fileNameOrNil : [[fileURL lastPathComponent] stringByAppendingPathExtension:[fileURL pathExtension]]; + [self appendPartWithHeaders:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"file; filename=\"%@\"", fileName] forKey:@"Content-Disposition"] body:data]; +} + +- (void)appendData:(NSData *)data { + [self appendString:[[[NSString alloc] initWithData:data encoding:self.stringEncoding] autorelease]]; +} + +- (void)appendString:(NSString *)string { + [self.lines addObject:string]; +} + +- (void)appendBlankLine { + [self appendString:@""]; +} + +@end diff --git a/AFNetworking/NSMutableURLRequest+AFNetworking.h b/AFNetworking/NSMutableURLRequest+AFNetworking.h deleted file mode 100644 index 7823f12..0000000 --- a/AFNetworking/NSMutableURLRequest+AFNetworking.h +++ /dev/null @@ -1,33 +0,0 @@ -// NSMutableURLRequest+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 - -@interface NSMutableURLRequest (AFNetworking) - -- (void)setHTTPBodyWithData:(NSData *)data - mimeType:(NSString *)mimeType - forParameterNamed:(NSString *)parameterName - parameters:(NSDictionary *)parameters - useGzipCompression:(BOOL)useGzipCompression; - -@end diff --git a/AFNetworking/NSMutableURLRequest+AFNetworking.m b/AFNetworking/NSMutableURLRequest+AFNetworking.m deleted file mode 100644 index 3d02670..0000000 --- a/AFNetworking/NSMutableURLRequest+AFNetworking.m +++ /dev/null @@ -1,76 +0,0 @@ -// NSMutableURLRequest+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 "NSMutableURLRequest+AFNetworking.h" -#import "NSData+AFNetworking.h" - -@implementation NSMutableURLRequest (AFNetworking) - -- (void)setHTTPBodyWithData:(NSData *)data - mimeType:(NSString *)mimeType - forParameterNamed:(NSString *)parameterName - parameters:(NSDictionary *)parameters - useGzipCompression:(BOOL)useGzipCompression -{ - if ([[self HTTPMethod] isEqualToString:@"GET"]) { - [self setHTTPMethod:@"POST"]; - } - - NSString *filename = [[NSString stringWithFormat:@"%d", [[NSDate date] hash]] stringByAppendingPathExtension:[mimeType lastPathComponent]]; - - static NSString * const boundary = @"----Boundary+0xAbCdEfGbOuNdArY"; - [self setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] forHTTPHeaderField:@"Content-Type"]; - - NSMutableData *mutableData = [NSMutableData data]; - [mutableData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; - - id key; - NSEnumerator *enumerator = [parameters keyEnumerator]; - while ((key = [enumerator nextObject])) { - [mutableData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]]; - [mutableData appendData:[[NSString stringWithFormat:@"%@", [parameters valueForKey:key]] dataUsingEncoding:NSUTF8StringEncoding]]; - [mutableData appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; - } - - [mutableData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"", parameterName, filename, nil] dataUsingEncoding:NSUTF8StringEncoding]]; - [mutableData appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; - [mutableData appendData:[[NSString stringWithFormat:@"Content-Type: %@", mimeType] dataUsingEncoding:NSUTF8StringEncoding]]; - [mutableData appendData:[@"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; - [mutableData appendData:data]; - [mutableData appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; - - if (useGzipCompression) { - NSError *error = nil; - NSData *compressedData = [mutableData dataByGZipCompressingWithError:&error]; - - if (!error && compressedData) { - [self setHTTPBody:compressedData]; - - // Content-Encoding HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11 - [self setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"]; - } - } else { - [self setHTTPBody:mutableData]; - } -} - -@end diff --git a/Example/AFNetworking Example.xcodeproj/project.pbxproj b/Example/AFNetworking Example.xcodeproj/project.pbxproj index 08cc028..f8a66cf 100644 --- a/Example/AFNetworking Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking Example.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - F85CE2DC13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F85CE2DB13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m */; }; F874B5D913E0AA6500B28E3E /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */; }; F874B5DA13E0AA6500B28E3E /* AFImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CA13E0AA6500B28E3E /* AFImageCache.m */; }; F874B5DB13E0AA6500B28E3E /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */; }; @@ -34,8 +33,6 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - F85CE2DA13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSMutableURLRequest+AFNetworking.h"; path = "../AFNetworking/NSMutableURLRequest+AFNetworking.h"; sourceTree = ""; }; - F85CE2DB13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSMutableURLRequest+AFNetworking.m"; path = "../AFNetworking/NSMutableURLRequest+AFNetworking.m"; sourceTree = ""; }; F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFHTTPRequestOperation.m; path = ../AFNetworking/AFHTTPRequestOperation.m; sourceTree = ""; }; F874B5CA13E0AA6500B28E3E /* AFImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageCache.m; path = ../AFNetworking/AFImageCache.m; sourceTree = ""; }; F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageRequestOperation.m; path = ../AFNetworking/AFImageRequestOperation.m; sourceTree = ""; }; @@ -101,8 +98,6 @@ F85CE2D613EC47BC00BFAE01 /* Categories */ = { isa = PBXGroup; children = ( - F85CE2DA13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.h */, - F85CE2DB13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m */, F874B5D713E0AA6500B28E3E /* UIImage+AFNetworking.h */, F874B5CF13E0AA6500B28E3E /* UIImage+AFNetworking.m */, F874B5D813E0AA6500B28E3E /* UIImageView+AFNetworking.h */, @@ -348,7 +343,6 @@ F874B5DE13E0AA6500B28E3E /* AFRestClient.m in Sources */, F874B5DF13E0AA6500B28E3E /* UIImage+AFNetworking.m in Sources */, F874B5E013E0AA6500B28E3E /* UIImageView+AFNetworking.m in Sources */, - F85CE2DC13EC4A4200BFAE01 /* NSMutableURLRequest+AFNetworking.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 341153605fc753353755e78110783f7af5c55126 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 14:22:21 -0500 Subject: [PATCH 16/41] Fixing a few things with AFRestClient multipart request functionality --- AFNetworking/AFRestClient.m | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/AFNetworking/AFRestClient.m b/AFNetworking/AFRestClient.m index 210aa9d..ec29e3c 100644 --- a/AFNetworking/AFRestClient.m +++ b/AFNetworking/AFRestClient.m @@ -37,7 +37,7 @@ static NSString * AFMultipartFormFinalBoundary() { @interface AFMutableMultipartFormData : NSObject { @private NSStringEncoding _stringEncoding; - NSMutableArray *_lines; + NSMutableArray *_mutableLines; } - (id)initWithStringEncoding:(NSStringEncoding)encoding; @@ -197,7 +197,7 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS } NSMutableURLRequest *request = [self requestWithMethod:method path:path parameters:nil]; - __block AFMutableMultipartFormData *formData = [[AFMutableMultipartFormData alloc] init]; + __block AFMutableMultipartFormData *formData = [[AFMutableMultipartFormData alloc] initWithStringEncoding:self.stringEncoding]; id key = nil; NSEnumerator *enumerator = [parameters keyEnumerator]; @@ -276,14 +276,14 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS // multipart/form-data; see http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.2 @interface AFMutableMultipartFormData () @property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding; -@property (readwrite, nonatomic, retain) NSMutableArray *lines; +@property (readwrite, nonatomic, retain) NSMutableArray *mutableLines; - (void)appendBlankLine; @end @implementation AFMutableMultipartFormData @synthesize stringEncoding = _stringEncoding; -@synthesize lines = _lines; +@synthesize mutableLines = _mutableLines; - (id)initWithStringEncoding:(NSStringEncoding)encoding { self = [super init]; @@ -292,25 +292,31 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS } self.stringEncoding = encoding; - self.lines = [NSMutableArray array]; + self.mutableLines = [NSMutableArray array]; return self; } - (void)dealloc { - [_lines release]; + [_mutableLines release]; [super dealloc]; } - (NSData *)data { - NSLog(@"DATA: %@", [[self.lines componentsJoinedByString:kAFMultipartFormLineDelimiter] stringByAppendingString:AFMultipartFormFinalBoundary()]); + if ([self.mutableLines count] == 0) { + return nil; + } - return [[[[self.lines componentsJoinedByString:kAFMultipartFormLineDelimiter] stringByAppendingString:AFMultipartFormFinalBoundary()] stringByAppendingString:kAFMultipartFormLineDelimiter] dataUsingEncoding:self.stringEncoding]; + return [[[[self.mutableLines componentsJoinedByString:kAFMultipartFormLineDelimiter] stringByAppendingString:kAFMultipartFormLineDelimiter] stringByAppendingString:AFMultipartFormFinalBoundary()] dataUsingEncoding:self.stringEncoding]; } #pragma mark - AFMultipartFormDataProxy - (void)appendPartWithHeaders:(NSDictionary *)headers body:(NSData *)body { + if ([self.mutableLines count] > 0) { + [self appendString:AFMultipartFormEncapsulationBoundary()]; + } + for (NSString *field in [headers allKeys]) { [self appendString:[NSString stringWithFormat:@"%@: %@", field, [headers valueForKey:field]]]; } @@ -339,7 +345,7 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS } - (void)appendString:(NSString *)string { - [self.lines addObject:string]; + [self.mutableLines addObject:string]; } - (void)appendBlankLine { From f422cafe144dcdc30c9270418f9c1ccc7de348ce Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 14:32:30 -0500 Subject: [PATCH 17/41] Removing UIImage category in favor of static function to resize images in UIImageView category implementation --- AFNetworking/UIImage+AFNetworking.h | 28 ------- AFNetworking/UIImage+AFNetworking.m | 80 ------------------- AFNetworking/UIImageView+AFNetworking.m | 32 +++++++- .../project.pbxproj | 6 -- 4 files changed, 30 insertions(+), 116 deletions(-) delete mode 100644 AFNetworking/UIImage+AFNetworking.h delete mode 100644 AFNetworking/UIImage+AFNetworking.m diff --git a/AFNetworking/UIImage+AFNetworking.h b/AFNetworking/UIImage+AFNetworking.h deleted file mode 100644 index 994095d..0000000 --- a/AFNetworking/UIImage+AFNetworking.h +++ /dev/null @@ -1,28 +0,0 @@ -// UIImage+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. - -@interface UIImage (AFNetworking) - -+ (UIImage *)imageByScalingAndCroppingImage:(UIImage *)image size:(CGSize)size; -+ (UIImage *)imageByRoundingCornersOfImage:(UIImage *)image corners:(UIRectCorner)corners cornerRadii:(CGSize)radii; - -@end diff --git a/AFNetworking/UIImage+AFNetworking.m b/AFNetworking/UIImage+AFNetworking.m deleted file mode 100644 index d95db3e..0000000 --- a/AFNetworking/UIImage+AFNetworking.m +++ /dev/null @@ -1,80 +0,0 @@ -// UIImage+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 "UIImage+AFNetworking.h" - -@implementation UIImage (AFNetworking) - -+ (UIImage *)imageByScalingAndCroppingImage:(UIImage *)image size:(CGSize)size { - if (image == nil) { - return nil; - } else if (CGSizeEqualToSize(image.size, size) || CGSizeEqualToSize(size, CGSizeZero)) { - return image; - } - - CGSize scaledSize = size; - CGPoint thumbnailPoint = CGPointZero; - - CGFloat widthFactor = size.width / image.size.width; - CGFloat heightFactor = size.height / image.size.height; - CGFloat scaleFactor = (widthFactor > heightFactor) ? widthFactor : heightFactor; - scaledSize.width = image.size.width * scaleFactor; - scaledSize.height = image.size.height * scaleFactor; - if (widthFactor > heightFactor) { - thumbnailPoint.y = (size.height - scaledSize.height) * 0.5; - } else if (widthFactor < heightFactor) { - thumbnailPoint.x = (size.width - scaledSize.width) * 0.5; - } - - UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); - [image drawInRect:CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledSize.width, scaledSize.height)]; - UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return newImage; -} - -+ (UIImage *)imageByRoundingCornersOfImage:(UIImage *)image corners:(UIRectCorner)corners cornerRadii:(CGSize)radii { - if (image == nil) { - return nil; - } else if(UIGraphicsBeginImageContextWithOptions != NULL) { - UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0); - } else { - UIGraphicsBeginImageContext(image.size); - } - - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextBeginPath(context); - CGContextAddPath(context, [[UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.0f, 0.0f, image.size.width, image.size.height) byRoundingCorners:corners cornerRadii:radii] CGPath]); - CGContextClosePath(context); - CGContextClip(context); - - CGRect rect = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height); - [image drawInRect:rect]; - - UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return newImage; -} - -@end diff --git a/AFNetworking/UIImageView+AFNetworking.m b/AFNetworking/UIImageView+AFNetworking.m index 70dddd0..cd68748 100644 --- a/AFNetworking/UIImageView+AFNetworking.m +++ b/AFNetworking/UIImageView+AFNetworking.m @@ -24,10 +24,38 @@ #import #import "UIImageView+AFNetworking.h" -#import "UIImage+AFNetworking.h" #import "AFImageCache.h" +static UIImage * AFImageByScalingAndCroppingImageToSize(UIImage *image, CGSize size) { + if (image == nil) { + return nil; + } else if (CGSizeEqualToSize(image.size, size) || CGSizeEqualToSize(size, CGSizeZero)) { + return image; + } + + CGSize scaledSize = size; + CGPoint thumbnailPoint = CGPointZero; + + CGFloat widthFactor = size.width / image.size.width; + CGFloat heightFactor = size.height / image.size.height; + CGFloat scaleFactor = (widthFactor > heightFactor) ? widthFactor : heightFactor; + scaledSize.width = image.size.width * scaleFactor; + scaledSize.height = image.size.height * scaleFactor; + if (widthFactor > heightFactor) { + thumbnailPoint.y = (size.height - scaledSize.height) * 0.5; + } else if (widthFactor < heightFactor) { + thumbnailPoint.x = (size.width - scaledSize.width) * 0.5; + } + + UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); + [image drawInRect:CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledSize.width, scaledSize.height)]; + UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return newImage; +} + static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOperation"; @interface UIImageView (_AFNetworking) @@ -104,7 +132,7 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp self.imageRequestOperation = [AFImageRequestOperation operationWithRequest:request imageProcessingBlock:^UIImage *(UIImage *image) { if (placeholderImage) { - image = [UIImage imageByScalingAndCroppingImage:image size:placeholderImage.size]; + image = AFImageByScalingAndCroppingImageToSize(image, placeholderImage.size); } return image; diff --git a/Example/AFNetworking Example.xcodeproj/project.pbxproj b/Example/AFNetworking Example.xcodeproj/project.pbxproj index f8a66cf..a153620 100644 --- a/Example/AFNetworking Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking Example.xcodeproj/project.pbxproj @@ -13,7 +13,6 @@ F874B5DC13E0AA6500B28E3E /* AFJSONRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CC13E0AA6500B28E3E /* AFJSONRequestOperation.m */; }; F874B5DD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m */; }; F874B5DE13E0AA6500B28E3E /* AFRestClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CE13E0AA6500B28E3E /* AFRestClient.m */; }; - F874B5DF13E0AA6500B28E3E /* UIImage+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CF13E0AA6500B28E3E /* UIImage+AFNetworking.m */; }; F874B5E013E0AA6500B28E3E /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5D013E0AA6500B28E3E /* UIImageView+AFNetworking.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 */; }; @@ -39,7 +38,6 @@ F874B5CC13E0AA6500B28E3E /* AFJSONRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFJSONRequestOperation.m; path = ../AFNetworking/AFJSONRequestOperation.m; sourceTree = ""; }; F874B5CD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFNetworkActivityIndicatorManager.m; path = ../AFNetworking/AFNetworkActivityIndicatorManager.m; sourceTree = ""; }; F874B5CE13E0AA6500B28E3E /* AFRestClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFRestClient.m; path = ../AFNetworking/AFRestClient.m; sourceTree = ""; }; - F874B5CF13E0AA6500B28E3E /* UIImage+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImage+AFNetworking.m"; path = "../AFNetworking/UIImage+AFNetworking.m"; sourceTree = ""; }; F874B5D013E0AA6500B28E3E /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+AFNetworking.m"; path = "../AFNetworking/UIImageView+AFNetworking.m"; sourceTree = ""; }; F874B5D113E0AA6500B28E3E /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFHTTPRequestOperation.h; path = ../AFNetworking/AFHTTPRequestOperation.h; sourceTree = ""; }; F874B5D213E0AA6500B28E3E /* AFImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFImageCache.h; path = ../AFNetworking/AFImageCache.h; sourceTree = ""; }; @@ -47,7 +45,6 @@ F874B5D413E0AA6500B28E3E /* AFJSONRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFJSONRequestOperation.h; path = ../AFNetworking/AFJSONRequestOperation.h; sourceTree = ""; }; F874B5D513E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFNetworkActivityIndicatorManager.h; path = ../AFNetworking/AFNetworkActivityIndicatorManager.h; sourceTree = ""; }; F874B5D613E0AA6500B28E3E /* AFRestClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = AFRestClient.h; path = ../AFNetworking/AFRestClient.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - F874B5D713E0AA6500B28E3E /* UIImage+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImage+AFNetworking.h"; path = "../AFNetworking/UIImage+AFNetworking.h"; sourceTree = ""; }; F874B5D813E0AA6500B28E3E /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImageView+AFNetworking.h"; path = "../AFNetworking/UIImageView+AFNetworking.h"; sourceTree = ""; }; F8D25D101396A9C400CF3BD6 /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = ""; }; F8D25D111396A9C400CF3BD6 /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = ""; }; @@ -98,8 +95,6 @@ F85CE2D613EC47BC00BFAE01 /* Categories */ = { isa = PBXGroup; children = ( - F874B5D713E0AA6500B28E3E /* UIImage+AFNetworking.h */, - F874B5CF13E0AA6500B28E3E /* UIImage+AFNetworking.m */, F874B5D813E0AA6500B28E3E /* UIImageView+AFNetworking.h */, F874B5D013E0AA6500B28E3E /* UIImageView+AFNetworking.m */, ); @@ -341,7 +336,6 @@ F874B5DC13E0AA6500B28E3E /* AFJSONRequestOperation.m in Sources */, F874B5DD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m in Sources */, F874B5DE13E0AA6500B28E3E /* AFRestClient.m in Sources */, - F874B5DF13E0AA6500B28E3E /* UIImage+AFNetworking.m in Sources */, F874B5E013E0AA6500B28E3E /* UIImageView+AFNetworking.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; From db4c852e3d01a1c675ca2020edcfa5ebdd129bb7 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 15:33:20 -0500 Subject: [PATCH 18/41] [Issue #33] Changing return type of class method object contructors from id to an actual instance of that class --- AFNetworking/AFHTTPRequestOperation.h | 12 ++++++------ AFNetworking/AFHTTPRequestOperation.m | 12 ++++++------ AFNetworking/AFImageCache.h | 2 +- AFNetworking/AFImageCache.m | 4 ++-- AFNetworking/AFImageRequestOperation.h | 14 +++++++------- AFNetworking/AFImageRequestOperation.m | 20 ++++++++------------ AFNetworking/AFJSONRequestOperation.h | 20 ++++++++++---------- AFNetworking/AFJSONRequestOperation.m | 22 +++++++++++----------- Example/Classes/AFGowallaAPIClient.h | 2 +- Example/Classes/AFGowallaAPIClient.m | 5 ++--- 10 files changed, 54 insertions(+), 59 deletions(-) diff --git a/AFNetworking/AFHTTPRequestOperation.h b/AFNetworking/AFHTTPRequestOperation.h index 532323d..12d0260 100644 --- a/AFNetworking/AFHTTPRequestOperation.h +++ b/AFNetworking/AFHTTPRequestOperation.h @@ -82,8 +82,8 @@ extern NSString * const AFHTTPOperationDidFinishNotification; @return A new HTTP request operation */ -+ (id)operationWithRequest:(NSURLRequest *)urlRequest - completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error))completion; ++ (AFHTTPRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest + completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error))completion; /** Creates and returns an `AFHTTPRequestOperation` object and sets the specified input and output streams, and completion callback. @@ -97,10 +97,10 @@ extern NSString * const AFHTTPOperationDidFinishNotification; @return A new HTTP request operation */ -+ (id)operationWithRequest:(NSURLRequest *)urlRequest - inputStream:(NSInputStream *)inputStream - outputStream:(NSOutputStream *)outputStream - completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))completion; ++ (AFHTTPRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest + inputStream:(NSInputStream *)inputStream + outputStream:(NSOutputStream *)outputStream + completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))completion; ///--------------------------------- /// @name Setting Progress Callbacks diff --git a/AFNetworking/AFHTTPRequestOperation.m b/AFNetworking/AFHTTPRequestOperation.m index 8d22647..af4c841 100644 --- a/AFNetworking/AFHTTPRequestOperation.m +++ b/AFNetworking/AFHTTPRequestOperation.m @@ -134,7 +134,7 @@ static NSThread *_networkRequestThread = nil; return _networkRequestThread; } -+ (id)operationWithRequest:(NSURLRequest *)urlRequest ++ (AFHTTPRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error))completion { AFHTTPRequestOperation *operation = [[[self alloc] initWithRequest:urlRequest] autorelease]; @@ -143,10 +143,10 @@ static NSThread *_networkRequestThread = nil; return operation; } -+ (id)operationWithRequest:(NSURLRequest *)urlRequest - inputStream:(NSInputStream *)inputStream - outputStream:(NSOutputStream *)outputStream - completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))completion ++ (AFHTTPRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest + inputStream:(NSInputStream *)inputStream + outputStream:(NSOutputStream *)outputStream + completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))completion { NSMutableURLRequest *mutableURLRequest = [[urlRequest mutableCopy] autorelease]; if (inputStream) { @@ -175,7 +175,7 @@ static NSThread *_networkRequestThread = nil; self.request = urlRequest; - self.runLoopModes = [NSSet setWithObjects:NSRunLoopCommonModes, nil]; + self.runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes]; self.state = AFHTTPOperationReadyState; diff --git a/AFNetworking/AFImageCache.h b/AFNetworking/AFImageCache.h index 35b10b3..f85a48f 100644 --- a/AFNetworking/AFImageCache.h +++ b/AFNetworking/AFImageCache.h @@ -25,7 +25,7 @@ @interface AFImageCache : NSCache -+ (id)sharedImageCache; ++ (AFImageCache *)sharedImageCache; - (UIImage *)cachedImageForRequest:(NSURLRequest *)urlRequest cacheName:(NSString *)cacheName; diff --git a/AFNetworking/AFImageCache.m b/AFNetworking/AFImageCache.m index 521a788..968b574 100644 --- a/AFNetworking/AFImageCache.m +++ b/AFNetworking/AFImageCache.m @@ -28,8 +28,8 @@ static inline NSString * AFImageCacheKey(NSURLRequest *urlRequest, NSString *cac @implementation AFImageCache -+ (id)sharedImageCache { - static NSCache *_sharedImageCache = nil; ++ (AFImageCache *)sharedImageCache { + static AFImageCache *_sharedImageCache = nil; static dispatch_once_t oncePredicate; dispatch_once(&oncePredicate, ^{ diff --git a/AFNetworking/AFImageRequestOperation.h b/AFNetworking/AFImageRequestOperation.h index ccb2039..180c653 100644 --- a/AFNetworking/AFImageRequestOperation.h +++ b/AFNetworking/AFImageRequestOperation.h @@ -26,13 +26,13 @@ @interface AFImageRequestOperation : AFHTTPRequestOperation -+ (id)operationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(UIImage *image))success; ++ (AFImageRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest + success:(void (^)(UIImage *image))success; -+ (id)operationWithRequest:(NSURLRequest *)urlRequest - imageProcessingBlock:(UIImage *(^)(UIImage *))imageProcessingBlock - cacheName:(NSString *)cacheNameOrNil - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; ++ (AFImageRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest + imageProcessingBlock:(UIImage *(^)(UIImage *))imageProcessingBlock + cacheName:(NSString *)cacheNameOrNil + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; @end diff --git a/AFNetworking/AFImageRequestOperation.m b/AFNetworking/AFImageRequestOperation.m index b2f70e0..4962d1f 100644 --- a/AFNetworking/AFImageRequestOperation.m +++ b/AFNetworking/AFImageRequestOperation.m @@ -23,8 +23,6 @@ #import "AFImageRequestOperation.h" #import "AFImageCache.h" -#import "UIImage+AFNetworking.h" - static dispatch_queue_t af_image_request_operation_processing_queue; static dispatch_queue_t image_request_operation_processing_queue() { if (af_image_request_operation_processing_queue == NULL) { @@ -36,8 +34,8 @@ static dispatch_queue_t image_request_operation_processing_queue() { @implementation AFImageRequestOperation -+ (id)operationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(UIImage *image))success ++ (AFImageRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest + success:(void (^)(UIImage *image))success { return [self operationWithRequest:urlRequest imageProcessingBlock:nil cacheName:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { if (success) { @@ -46,13 +44,13 @@ static dispatch_queue_t image_request_operation_processing_queue() { } failure:nil]; } -+ (id)operationWithRequest:(NSURLRequest *)urlRequest - imageProcessingBlock:(UIImage *(^)(UIImage *))imageProcessingBlock - cacheName:(NSString *)cacheNameOrNil - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure ++ (AFImageRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest + imageProcessingBlock:(UIImage *(^)(UIImage *))imageProcessingBlock + cacheName:(NSString *)cacheNameOrNil + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure { - AFImageRequestOperation *operation = [self operationWithRequest:urlRequest completion:^(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error) { + return (AFImageRequestOperation *)[self operationWithRequest:urlRequest completion:^(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error) { dispatch_async(image_request_operation_processing_queue(), ^(void) { if (error) { if (failure) { @@ -81,8 +79,6 @@ static dispatch_queue_t image_request_operation_processing_queue() { } }); }]; - - return operation; } @end diff --git a/AFNetworking/AFJSONRequestOperation.h b/AFNetworking/AFJSONRequestOperation.h index 4d1a147..19e5e90 100644 --- a/AFNetworking/AFJSONRequestOperation.h +++ b/AFNetworking/AFJSONRequestOperation.h @@ -40,8 +40,8 @@ @return A new JSON request operation */ -+ (id)operationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(id JSON))success; ++ (AFJSONRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest + success:(void (^)(id JSON))success; /** Creates and returns an `AFJSONRequestOperation` object and sets the specified success and failure callbacks. @@ -56,9 +56,9 @@ @return A new JSON request operation */ -+ (id)operationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(id JSON))success - failure:(void (^)(NSError *error))failure; ++ (AFJSONRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest + success:(void (^)(id JSON))success + failure:(void (^)(NSError *error))failure; /** Creates and returns an `AFJSONRequestOperation` object and sets the specified success and failure callbacks, as well as the status codes and content types that are acceptable for a successful request. @@ -71,11 +71,11 @@ @return A new JSON request operation */ -+ (id)operationWithRequest:(NSURLRequest *)urlRequest - acceptableStatusCodes:(NSIndexSet *)acceptableStatusCodes - acceptableContentTypes:(NSSet *)acceptableContentTypes - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; ++ (AFJSONRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest + acceptableStatusCodes:(NSIndexSet *)acceptableStatusCodes + acceptableContentTypes:(NSSet *)acceptableContentTypes + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; ///---------------------------------- diff --git a/AFNetworking/AFJSONRequestOperation.m b/AFNetworking/AFJSONRequestOperation.m index 3f6b3bf..c855ebe 100644 --- a/AFNetworking/AFJSONRequestOperation.m +++ b/AFNetworking/AFJSONRequestOperation.m @@ -36,15 +36,15 @@ static dispatch_queue_t json_request_operation_processing_queue() { @implementation AFJSONRequestOperation -+ (id)operationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(id JSON))success ++ (AFJSONRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest + success:(void (^)(id JSON))success { return [self operationWithRequest:urlRequest success:success failure:nil]; } -+ (id)operationWithRequest:(NSURLRequest *)urlRequest - success:(void (^)(id JSON))success - failure:(void (^)(NSError *error))failure ++ (AFJSONRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest + success:(void (^)(id JSON))success + failure:(void (^)(NSError *error))failure { return [self operationWithRequest:urlRequest acceptableStatusCodes:[self defaultAcceptableStatusCodes] acceptableContentTypes:[self defaultAcceptableContentTypes] success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { if (success) { @@ -57,13 +57,13 @@ static dispatch_queue_t json_request_operation_processing_queue() { }]; } -+ (id)operationWithRequest:(NSURLRequest *)urlRequest - acceptableStatusCodes:(NSIndexSet *)acceptableStatusCodes - acceptableContentTypes:(NSSet *)acceptableContentTypes - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure ++ (AFJSONRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest + acceptableStatusCodes:(NSIndexSet *)acceptableStatusCodes + acceptableContentTypes:(NSSet *)acceptableContentTypes + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure { - return [self operationWithRequest:urlRequest completion:^(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error) { + return (AFJSONRequestOperation *)[self operationWithRequest:urlRequest completion:^(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error) { if (!error) { if (acceptableStatusCodes && ![acceptableStatusCodes containsIndex:[response statusCode]]) { NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; diff --git a/Example/Classes/AFGowallaAPIClient.h b/Example/Classes/AFGowallaAPIClient.h index 86600c9..e79d3e4 100644 --- a/Example/Classes/AFGowallaAPIClient.h +++ b/Example/Classes/AFGowallaAPIClient.h @@ -27,5 +27,5 @@ extern NSString * const kAFGowallaClientID; extern NSString * const kAFGowallaBaseURLString; @interface AFGowallaAPIClient : AFRestClient -+ (id)sharedClient; ++ (AFGowallaAPIClient *)sharedClient; @end diff --git a/Example/Classes/AFGowallaAPIClient.m b/Example/Classes/AFGowallaAPIClient.m index 21cab53..76ac24d 100644 --- a/Example/Classes/AFGowallaAPIClient.m +++ b/Example/Classes/AFGowallaAPIClient.m @@ -22,8 +22,6 @@ #import "AFGowallaAPIClient.h" -static AFGowallaAPIClient *_sharedClient = nil; - // Replace this with your own API Key, available at http://api.gowalla.com/api/keys/ NSString * const kAFGowallaClientID = @"e7ccb7d3d2414eb2af4663fc91eb2793"; @@ -31,7 +29,8 @@ NSString * const kAFGowallaBaseURLString = @"https://api.gowalla.com/"; @implementation AFGowallaAPIClient -+ (id)sharedClient { ++ (AFGowallaAPIClient *)sharedClient { + static AFGowallaAPIClient *_sharedClient = nil; static dispatch_once_t oncePredicate; dispatch_once(&oncePredicate, ^{ _sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:kAFGowallaBaseURLString]]; From 6832cd0e16694202a6896d3298752825f9205742 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 15:34:08 -0500 Subject: [PATCH 19/41] Adding #import for Foundation to AFJSONRequestOperation --- AFNetworking/AFJSONRequestOperation.h | 1 + 1 file changed, 1 insertion(+) diff --git a/AFNetworking/AFJSONRequestOperation.h b/AFNetworking/AFJSONRequestOperation.h index 19e5e90..bd89943 100644 --- a/AFNetworking/AFJSONRequestOperation.h +++ b/AFNetworking/AFJSONRequestOperation.h @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#import #import "AFHTTPRequestOperation.h" @interface AFJSONRequestOperation : AFHTTPRequestOperation From 3b81cd32a717b02b47e2d6410311216c72c4d854 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 15:50:22 -0500 Subject: [PATCH 20/41] Fixing optimization to not re-initiate duplicated calls to a UIImageView, by adding missing check to see if the last operation was cancelled --- AFNetworking/UIImageView+AFNetworking.m | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/AFNetworking/UIImageView+AFNetworking.m b/AFNetworking/UIImageView+AFNetworking.m index cd68748..da3454c 100644 --- a/AFNetworking/UIImageView+AFNetworking.m +++ b/AFNetworking/UIImageView+AFNetworking.m @@ -105,7 +105,7 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp placeholderImage:(UIImage *)placeholderImage success:(void (^)(UIImage *image, BOOL cacheUsed))success { - if (!url || [url isEqual:self.imageRequestOperation.request.URL]) { + if (!url || (![self.imageRequestOperation isCancelled] && [url isEqual:self.imageRequestOperation.request.URL])) { return; } else { [self cancelImageRequestOperation]; @@ -138,15 +138,17 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp return image; } cacheName:cacheName success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { if (self.imageRequestOperation && ![self.imageRequestOperation isCancelled]) { - if (success) { - success(image, NO); - } + dispatch_async(dispatch_get_main_queue(), ^{ + if (success) { + success(image, NO); + } - if ([[request URL] isEqual:[[self.imageRequestOperation request] URL]]) { - self.image = image; - } else { - self.image = placeholderImage; - } + if ([[request URL] isEqual:[[self.imageRequestOperation request] URL]]) { + self.image = image; + } else { + self.image = placeholderImage; + } + }); } } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) { self.imageRequestOperation = nil; From 69c48f85bb251e23f1aa5e274ecf169c73e2b1a7 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 15:50:42 -0500 Subject: [PATCH 21/41] Removing unused -layoutSubviews code in SpotTableViewCell --- Example/Classes/Views/SpotTableViewCell.m | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/Example/Classes/Views/SpotTableViewCell.m b/Example/Classes/Views/SpotTableViewCell.m index 5de7eb1..c8feb4c 100644 --- a/Example/Classes/Views/SpotTableViewCell.m +++ b/Example/Classes/Views/SpotTableViewCell.m @@ -73,27 +73,4 @@ self.detailTextLabel.text = nil; } -#pragma mark - UIView - -//- (void)layoutSubviews { -// [super layoutSubviews]; -// -// CGRect imageViewFrame = self.imageView.frame; -// CGRect textLabelFrame = self.textLabel.frame; -// CGRect detailTextLabelFrame = self.detailTextLabel.frame; -// -// imageViewFrame.origin = CGPointMake(10.0f, 10.0f); -// imageViewFrame.size = CGSizeMake(50.0f, 50.0f); -// -// textLabelFrame.origin.x = imageViewFrame.size.width + 25.0f; -// detailTextLabelFrame.origin.x = textLabelFrame.origin.x; -// -// textLabelFrame.size.width = 240.0f; -// detailTextLabelFrame.size.width = textLabelFrame.size.width; -// -// self.textLabel.frame = textLabelFrame; -// self.detailTextLabel.frame = detailTextLabelFrame; -// self.imageView.frame = CGRectIntegral(imageViewFrame); -//} - @end From abc04440f7133c997f0a47e6f8b65319c6a6988e Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 15:55:21 -0500 Subject: [PATCH 22/41] Adding documentation to constants in AFHTTPRequestOperation --- AFNetworking/AFHTTPRequestOperation.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/AFNetworking/AFHTTPRequestOperation.h b/AFNetworking/AFHTTPRequestOperation.h index 12d0260..5125b18 100644 --- a/AFNetworking/AFHTTPRequestOperation.h +++ b/AFNetworking/AFHTTPRequestOperation.h @@ -22,10 +22,21 @@ #import -// Error codes for AFNetworkingErrorDomain correspond to codes in NSURLErrorDomain +/** + Indicates an error occured in AFNetworking. + + @discussion Error codes for AFNetworkingErrorDomain correspond to codes in NSURLErrorDomain. + */ extern NSString * const AFNetworkingErrorDomain; +/** + Posted when an operation begins executing. + */ extern NSString * const AFHTTPOperationDidStartNotification; + +/** + Posted when an operation finishes. + */ extern NSString * const AFHTTPOperationDidFinishNotification; /** From 9a78cc54cd47cee8fd3759d3bb6309318af7a871 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 16:07:25 -0500 Subject: [PATCH 23/41] Dispatching callbacks to main thread for JSON requests --- AFNetworking/AFJSONRequestOperation.m | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/AFNetworking/AFJSONRequestOperation.m b/AFNetworking/AFJSONRequestOperation.m index c855ebe..9e8e443 100644 --- a/AFNetworking/AFJSONRequestOperation.m +++ b/AFNetworking/AFJSONRequestOperation.m @@ -84,11 +84,15 @@ static dispatch_queue_t json_request_operation_processing_queue() { if (error) { if (failure) { - failure(request, response, error); + dispatch_async(dispatch_get_main_queue(), ^{ + failure(request, response, error); + }); } } else if ([data length] == 0) { if (success) { - success(request, response, nil); + dispatch_async(dispatch_get_main_queue(), ^{ + success(request, response, nil); + }); } } else { dispatch_async(json_request_operation_processing_queue(), ^(void) { @@ -104,7 +108,7 @@ static dispatch_queue_t json_request_operation_processing_queue() { JSON = [[JSONDecoder decoder] objectWithData:data error:&JSONError]; #endif - dispatch_sync(dispatch_get_main_queue(), ^(void) { + dispatch_async(dispatch_get_main_queue(), ^(void) { if (JSONError) { if (failure) { failure(request, response, JSONError); From 3512b3b606377ddd0873807580dab5f8522afa65 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 16:52:22 -0500 Subject: [PATCH 24/41] Dispatching callbacks to main thread for Image requests --- AFNetworking/AFImageRequestOperation.m | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFImageRequestOperation.m b/AFNetworking/AFImageRequestOperation.m index 4962d1f..c2d5cf5 100644 --- a/AFNetworking/AFImageRequestOperation.m +++ b/AFNetworking/AFImageRequestOperation.m @@ -54,7 +54,9 @@ static dispatch_queue_t image_request_operation_processing_queue() { dispatch_async(image_request_operation_processing_queue(), ^(void) { if (error) { if (failure) { - failure(request, response, error); + dispatch_async(dispatch_get_main_queue(), ^(void) { + failure(request, response, error); + }); } } else { UIImage *image = nil; @@ -69,7 +71,7 @@ static dispatch_queue_t image_request_operation_processing_queue() { image = imageProcessingBlock(image); } - dispatch_sync(dispatch_get_main_queue(), ^(void) { + dispatch_async(dispatch_get_main_queue(), ^(void) { if (success) { success(request, response, image); } From e7aba7d47ae30f7b3411a81fc165ffc1d55ed474 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 17:13:20 -0500 Subject: [PATCH 25/41] Making most explicit UIImageView image setting method take NSURLRequest, to allow for overriding cache policy, timeout interval, and other request properties --- AFNetworking/UIImageView+AFNetworking.h | 6 +++--- AFNetworking/UIImageView+AFNetworking.m | 26 +++++++++++++------------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/AFNetworking/UIImageView+AFNetworking.h b/AFNetworking/UIImageView+AFNetworking.h index d983f36..16f8889 100644 --- a/AFNetworking/UIImageView+AFNetworking.h +++ b/AFNetworking/UIImageView+AFNetworking.h @@ -30,9 +30,9 @@ - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage; -- (void)setImageWithURL:(NSURL *)url - placeholderImage:(UIImage *)placeholderImage - success:(void (^)(UIImage *image, BOOL cacheUsed))block; +- (void)setImageWithURLRequest:(NSURLRequest *)urlRequest + placeholderImage:(UIImage *)placeholderImage + success:(void (^)(UIImage *image, BOOL cacheUsed))success; - (void)cancelImageRequestOperation; diff --git a/AFNetworking/UIImageView+AFNetworking.m b/AFNetworking/UIImageView+AFNetworking.m index da3454c..7140fd5 100644 --- a/AFNetworking/UIImageView+AFNetworking.m +++ b/AFNetworking/UIImageView+AFNetworking.m @@ -98,29 +98,29 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage { - [self setImageWithURL:url placeholderImage:placeholderImage success:nil]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLCacheStorageAllowed timeoutInterval:30.0]; + [request setHTTPShouldHandleCookies:NO]; + [request setHTTPShouldUsePipelining:YES]; + + [self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil]; } -- (void)setImageWithURL:(NSURL *)url - placeholderImage:(UIImage *)placeholderImage - success:(void (^)(UIImage *image, BOOL cacheUsed))success +- (void)setImageWithURLRequest:(NSURLRequest *)urlRequest + placeholderImage:(UIImage *)placeholderImage + success:(void (^)(UIImage *image, BOOL cacheUsed))success { - if (!url || (![self.imageRequestOperation isCancelled] && [url isEqual:self.imageRequestOperation.request.URL])) { + if (![urlRequest URL] || (![self.imageRequestOperation isCancelled] && [[urlRequest URL] isEqual:self.imageRequestOperation.request.URL])) { return; } else { [self cancelImageRequestOperation]; } - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLCacheStorageAllowed timeoutInterval:30.0]; - [request setHTTPShouldHandleCookies:NO]; - [request setHTTPShouldUsePipelining:YES]; - NSString *cacheName = @"UIImageView"; if (placeholderImage) { cacheName = [cacheName stringByAppendingFormat:@"(%@)", NSStringFromCGSize(placeholderImage.size)]; } - UIImage *cachedImage = [[AFImageCache sharedImageCache] cachedImageForRequest:request cacheName:cacheName]; + UIImage *cachedImage = [[AFImageCache sharedImageCache] cachedImageForRequest:urlRequest cacheName:cacheName]; if (cachedImage) { self.image = cachedImage; @@ -130,7 +130,7 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp } else { self.image = placeholderImage; - self.imageRequestOperation = [AFImageRequestOperation operationWithRequest:request imageProcessingBlock:^UIImage *(UIImage *image) { + self.imageRequestOperation = [AFImageRequestOperation operationWithRequest:urlRequest imageProcessingBlock:^UIImage *(UIImage *image) { if (placeholderImage) { image = AFImageByScalingAndCroppingImageToSize(image, placeholderImage.size); } @@ -154,7 +154,9 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp self.imageRequestOperation = nil; }]; - [[[self class] sharedImageRequestOperationQueue] addOperation:self.imageRequestOperation]; + if ([urlRequest cachePolicy] != NSURLCacheStorageNotAllowed) { + [[[self class] sharedImageRequestOperationQueue] addOperation:self.imageRequestOperation]; + } } } From c0c79a7675a8d625ce623a4d2d0be3299f8fd10f Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 17:51:05 -0500 Subject: [PATCH 26/41] Further additions to AFRestClient documentation --- AFNetworking/AFHTTPRequestOperation.h | 6 ++-- AFNetworking/AFRestClient.h | 46 +++++++++++++++++++++------ AFNetworking/AFRestClient.m | 14 ++------ 3 files changed, 43 insertions(+), 23 deletions(-) diff --git a/AFNetworking/AFHTTPRequestOperation.h b/AFNetworking/AFHTTPRequestOperation.h index 5125b18..6072e3c 100644 --- a/AFNetworking/AFHTTPRequestOperation.h +++ b/AFNetworking/AFHTTPRequestOperation.h @@ -86,7 +86,7 @@ extern NSString * const AFHTTPOperationDidFinishNotification; /** Creates and returns an `AFHTTPRequestOperation` object and sets the specified completion callback. - @param urlRequest The request object to be loaded asynchronously during execution of the operation + @param urlRequest The request object to be loaded asynchronously during execution of the operation. @param completion A block object to be executed when the HTTP request operation is finished. This block has no return value and takes four arguments: the NSURLRequest sent from the client and the NSHTTPURLResponse received from the server, the NSData received by the server during the execution of the request, and an NSError, which will have been set if an error occured while loading the request. @see operationWithRequest:inputStream:outputStream:completion @@ -97,9 +97,9 @@ extern NSString * const AFHTTPOperationDidFinishNotification; completion:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSData *data, NSError *error))completion; /** - Creates and returns an `AFHTTPRequestOperation` object and sets the specified input and output streams, and completion callback. + Creates and returns a streaming `AFHTTPRequestOperation` object and sets the specified input and output streams, and completion callback. - @param urlRequest The request object to be loaded asynchronously during execution of the operation + @param urlRequest The request object to be loaded asynchronously during execution of the operation. @param inputStream The input stream object for reading data to be sent during the request. If set, the input stream is set as the HTTPBodyStream on the NSMutableURLRequest, and the request method is changed to `POST`. This argument may be `nil`. @param outputStream The output stream object for writing data received during the request. If set, data accumulated in NSURLConnectionDelegate methods will be sent to the output stream, and the NSData parameter in the completion block will be `nil`. This argument may be `nil`. @param completion A block object to be executed when the HTTP request operation is finished. This block has no return value and takes four arguments: the NSURLRequest sent from the client and the NSHTTPURLResponse received from the server, the NSData received by the server during the execution of the request, and an NSError, which will have been set if an error occured while loading the request. This argument may be `NULL`. diff --git a/AFNetworking/AFRestClient.h b/AFNetworking/AFRestClient.h index f420292..bf04285 100644 --- a/AFNetworking/AFRestClient.h +++ b/AFNetworking/AFRestClient.h @@ -34,12 +34,18 @@ } /** - An `NSURL` object that is used as the base for paths specified in methods such as `getPath:parameteres:success:failure` + The url used as the base for paths specified in methods such as `getPath:parameteres:success:failure` */ @property (readonly, nonatomic, retain) NSURL *baseURL; +/** + The string encoding used in constructing url requests. This is `NSUTF8StringEncoding` by default. + */ @property (nonatomic, assign) NSStringEncoding stringEncoding; +/** + The operation queue which manages operations enqueued by the REST client. + */ @property (readonly, nonatomic, retain) NSOperationQueue *operationQueue;; ///-------------------------------- @@ -101,17 +107,29 @@ ///------------------------------- /** - Creates an `NSMutableURLRequest` object with the specified HTTP method, resource path, and parameters, with the default HTTP headers specified for the client. + Creates an `NSMutableURLRequest` object with the specified HTTP method and resource path. If the HTTP method is `GET`, the parameters will be used to construct a url-encoded query string that is appended to the request's URL. If `POST`, `PUT`, or `DELETE`, the parameters will be encoded into a `application/x-www-form-urlencoded` HTTP body. - @param method The HTTP method for the request, such as `GET`, `POST`, `PUT`, or `DELETE` - @param path The resource path to be appended to the REST client's base URL and used as the request URL - @param parameters The parameters to be either set as a query string for `GET` requests, or form URL-encoded and set in the request HTTP body + @param method The HTTP method for the request, such as `GET`, `POST`, `PUT`, or `DELETE`. + @param path The resource path to be appended to the REST client's base URL and used as the request URL. + @param parameters The parameters to be either set as a query string for `GET` requests, or the request HTTP body. @return An `NSMutableURLRequest` object */ - (NSMutableURLRequest *)requestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters; +/** + Creates an `NSMutableURLRequest` object with the specified HTTP method and resource path, and constructs a `multipart/form-data` HTTP body, using the specified parameters and multipart form data block. + + @param method The HTTP method for the request. Must be either `POST`, `PUT`, or `DELETE`. + @param path The resource path to be appended to the REST client's base URL and used as the request URL. + @param parameters The parameters to be encoded and set in the request HTTP body. + @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormDataProxy` protocol. This can be used to upload files, encode HTTP body as JSON or XML, or specify multiple values for the same parameter, as one might for array values. + + @see AFMultipartFormDataProxy + + @return An `NSMutableURLRequest` object + */ - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters @@ -121,8 +139,14 @@ ///-------------------------------- /// @name Enqueuing HTTP Operations ///-------------------------------- -- (void)enqueueHTTPOperation:(AFHTTPRequestOperation *)operation; +/** + Constructs and enqueues an `AFHTTPRequestOperation` to the REST client's operation queue. + + @param request The request object to be loaded asynchronously during execution of the operation. + @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. + @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. + */ - (void)enqueueHTTPOperationWithRequest:(NSURLRequest *)request success:(void (^)(id response))success failure:(void (^)(NSError *error))failure; @@ -131,9 +155,13 @@ /// @name Cancelling HTTP Operations ///--------------------------------- -- (void)cancelHTTPOperationsWithRequest:(NSURLRequest *)request; - -- (void)cancelAllHTTPOperations; +/** + Cancels all operations in the REST client's operation queue that match the specified HTTP method and URL. + + @param method The HTTP method to match for the cancelled requests, such as `GET`, `POST`, `PUT`, or `DELETE`. + @param url The URL to match for the cancelled requests. + */ +- (void)cancelHTTPOperationsWithMethod:(NSString *)method andURL:(NSURL *)url; ///--------------------------- /// @name Making HTTP Requests diff --git a/AFNetworking/AFRestClient.m b/AFNetworking/AFRestClient.m index ec29e3c..b2d7f23 100644 --- a/AFNetworking/AFRestClient.m +++ b/AFNetworking/AFRestClient.m @@ -222,31 +222,23 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS return request; } -- (void)enqueueHTTPOperation:(AFHTTPRequestOperation *)operation { - [self.operationQueue addOperation:operation]; -} - - (void)enqueueHTTPOperationWithRequest:(NSURLRequest *)request success:(void (^)(id 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 enqueueHTTPOperation:operation]; + [self.operationQueue addOperation:operation]; } -- (void)cancelHTTPOperationsWithRequest:(NSURLRequest *)request { +- (void)cancelHTTPOperationsWithMethod:(NSString *)method andURL:(NSURL *)url { for (AFHTTPRequestOperation *operation in [self.operationQueue operations]) { - if ([[operation request] isEqual:request]) { + if ([[[operation request] HTTPMethod] isEqualToString:method] && [[[operation request] URL] isEqual:url]) { [operation cancel]; } } } -- (void)cancelAllHTTPOperations { - [self.operationQueue cancelAllOperations]; -} - #pragma mark - - (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success failure:(void (^)(NSError *error))failure { From ab91d075753c25defde2ccbf0fa6f7e588927b79 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 17:55:24 -0500 Subject: [PATCH 27/41] Renaming AFRestClient to AFRESTClient --- AFNetworking/{AFRestClient.h => AFRESTClient.h} | 2 +- AFNetworking/{AFRestClient.m => AFRESTClient.m} | 6 +++--- .../AFNetworking Example.xcodeproj/project.pbxproj | 12 ++++++------ Example/Classes/AFGowallaAPIClient.h | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) rename AFNetworking/{AFRestClient.h => AFRESTClient.h} (99%) rename AFNetworking/{AFRestClient.m => AFRESTClient.m} (99%) diff --git a/AFNetworking/AFRestClient.h b/AFNetworking/AFRESTClient.h similarity index 99% rename from AFNetworking/AFRestClient.h rename to AFNetworking/AFRESTClient.h index bf04285..5d514aa 100644 --- a/AFNetworking/AFRestClient.h +++ b/AFNetworking/AFRESTClient.h @@ -25,7 +25,7 @@ @protocol AFMultipartFormDataProxy; -@interface AFRestClient : NSObject { +@interface AFRESTClient : NSObject { @private NSURL *_baseURL; NSStringEncoding _stringEncoding; diff --git a/AFNetworking/AFRestClient.m b/AFNetworking/AFRESTClient.m similarity index 99% rename from AFNetworking/AFRestClient.m rename to AFNetworking/AFRESTClient.m index b2d7f23..ef596d6 100644 --- a/AFNetworking/AFRestClient.m +++ b/AFNetworking/AFRESTClient.m @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#import "AFRestClient.h" +#import "AFRESTClient.h" #import "AFJSONRequestOperation.h" static NSString * const kAFMultipartFormLineDelimiter = @"\r\n"; // CRLF @@ -83,13 +83,13 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, (CFStringRef)kAFLegalCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding)) autorelease]; } -@interface AFRestClient () +@interface AFRESTClient () @property (readwrite, nonatomic, retain) NSURL *baseURL; @property (readwrite, nonatomic, retain) NSMutableDictionary *defaultHeaders; @property (readwrite, nonatomic, retain) NSOperationQueue *operationQueue; @end -@implementation AFRestClient +@implementation AFRESTClient @synthesize baseURL = _baseURL; @synthesize stringEncoding = _stringEncoding; @synthesize defaultHeaders = _defaultHeaders; diff --git a/Example/AFNetworking Example.xcodeproj/project.pbxproj b/Example/AFNetworking Example.xcodeproj/project.pbxproj index a153620..f10cc62 100644 --- a/Example/AFNetworking Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking Example.xcodeproj/project.pbxproj @@ -12,7 +12,6 @@ F874B5DB13E0AA6500B28E3E /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */; }; F874B5DC13E0AA6500B28E3E /* AFJSONRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CC13E0AA6500B28E3E /* AFJSONRequestOperation.m */; }; F874B5DD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m */; }; - F874B5DE13E0AA6500B28E3E /* AFRestClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CE13E0AA6500B28E3E /* AFRestClient.m */; }; F874B5E013E0AA6500B28E3E /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5D013E0AA6500B28E3E /* UIImageView+AFNetworking.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 */; }; @@ -28,6 +27,7 @@ F8E469671395739D00DB05C8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469661395739D00DB05C8 /* Foundation.framework */; }; F8E469691395739D00DB05C8 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469681395739D00DB05C8 /* CoreGraphics.framework */; }; F8E469DF13957DD500DB05C8 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469DE13957DD500DB05C8 /* CoreLocation.framework */; }; + F8FBFA98142AA239001409DB /* AFRESTClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F8FBFA97142AA238001409DB /* AFRESTClient.m */; }; FF2B770D140DAC4E00A8DEC2 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FF2B770C140DAC4E00A8DEC2 /* libz.dylib */; }; /* End PBXBuildFile section */ @@ -37,14 +37,12 @@ F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageRequestOperation.m; path = ../AFNetworking/AFImageRequestOperation.m; sourceTree = ""; }; F874B5CC13E0AA6500B28E3E /* AFJSONRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFJSONRequestOperation.m; path = ../AFNetworking/AFJSONRequestOperation.m; sourceTree = ""; }; F874B5CD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFNetworkActivityIndicatorManager.m; path = ../AFNetworking/AFNetworkActivityIndicatorManager.m; sourceTree = ""; }; - F874B5CE13E0AA6500B28E3E /* AFRestClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFRestClient.m; path = ../AFNetworking/AFRestClient.m; sourceTree = ""; }; F874B5D013E0AA6500B28E3E /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+AFNetworking.m"; path = "../AFNetworking/UIImageView+AFNetworking.m"; sourceTree = ""; }; F874B5D113E0AA6500B28E3E /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFHTTPRequestOperation.h; path = ../AFNetworking/AFHTTPRequestOperation.h; sourceTree = ""; }; F874B5D213E0AA6500B28E3E /* AFImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFImageCache.h; path = ../AFNetworking/AFImageCache.h; sourceTree = ""; }; F874B5D313E0AA6500B28E3E /* AFImageRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFImageRequestOperation.h; path = ../AFNetworking/AFImageRequestOperation.h; sourceTree = ""; }; F874B5D413E0AA6500B28E3E /* AFJSONRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFJSONRequestOperation.h; path = ../AFNetworking/AFJSONRequestOperation.h; sourceTree = ""; }; F874B5D513E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFNetworkActivityIndicatorManager.h; path = ../AFNetworking/AFNetworkActivityIndicatorManager.h; sourceTree = ""; }; - F874B5D613E0AA6500B28E3E /* AFRestClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = AFRestClient.h; path = ../AFNetworking/AFRestClient.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; F874B5D813E0AA6500B28E3E /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImageView+AFNetworking.h"; path = "../AFNetworking/UIImageView+AFNetworking.h"; sourceTree = ""; }; F8D25D101396A9C400CF3BD6 /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = ""; }; F8D25D111396A9C400CF3BD6 /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = ""; }; @@ -73,6 +71,8 @@ F8E469E013957DF100DB05C8 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; F8E469E213957DF700DB05C8 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; F8E469E413957E0400DB05C8 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + F8FBFA96142AA237001409DB /* AFRESTClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFRESTClient.h; path = ../AFNetworking/AFRESTClient.h; sourceTree = ""; }; + F8FBFA97142AA238001409DB /* AFRESTClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFRESTClient.m; path = ../AFNetworking/AFRESTClient.m; sourceTree = ""; }; FF2B770C140DAC4E00A8DEC2 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -227,8 +227,8 @@ F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */, F874B5D413E0AA6500B28E3E /* AFJSONRequestOperation.h */, F874B5CC13E0AA6500B28E3E /* AFJSONRequestOperation.m */, - F874B5D613E0AA6500B28E3E /* AFRestClient.h */, - F874B5CE13E0AA6500B28E3E /* AFRestClient.m */, + F8FBFA96142AA237001409DB /* AFRESTClient.h */, + F8FBFA97142AA238001409DB /* AFRESTClient.m */, F874B5D313E0AA6500B28E3E /* AFImageRequestOperation.h */, F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */, F874B5D213E0AA6500B28E3E /* AFImageCache.h */, @@ -335,8 +335,8 @@ F874B5DB13E0AA6500B28E3E /* AFImageRequestOperation.m in Sources */, F874B5DC13E0AA6500B28E3E /* AFJSONRequestOperation.m in Sources */, F874B5DD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m in Sources */, - F874B5DE13E0AA6500B28E3E /* AFRestClient.m in Sources */, F874B5E013E0AA6500B28E3E /* UIImageView+AFNetworking.m in Sources */, + F8FBFA98142AA239001409DB /* AFRESTClient.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/Classes/AFGowallaAPIClient.h b/Example/Classes/AFGowallaAPIClient.h index e79d3e4..a744ae0 100644 --- a/Example/Classes/AFGowallaAPIClient.h +++ b/Example/Classes/AFGowallaAPIClient.h @@ -21,11 +21,11 @@ // THE SOFTWARE. #import -#import "AFRestClient.h" +#import "AFRESTClient.h" extern NSString * const kAFGowallaClientID; extern NSString * const kAFGowallaBaseURLString; -@interface AFGowallaAPIClient : AFRestClient +@interface AFGowallaAPIClient : AFRESTClient + (AFGowallaAPIClient *)sharedClient; @end From cad7d40642c7289246bd9a97cc8ec4e26ac7b7d0 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 17:56:12 -0500 Subject: [PATCH 28/41] Fixing AFRESTClient filenames in preambles --- AFNetworking/AFRESTClient.h | 2 +- AFNetworking/AFRESTClient.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFRESTClient.h b/AFNetworking/AFRESTClient.h index 5d514aa..298fa87 100644 --- a/AFNetworking/AFRESTClient.h +++ b/AFNetworking/AFRESTClient.h @@ -1,4 +1,4 @@ -// AFRestClient.h +// AFRESTClient.h // // Copyright (c) 2011 Gowalla (http://gowalla.com/) // diff --git a/AFNetworking/AFRESTClient.m b/AFNetworking/AFRESTClient.m index ef596d6..43279cd 100644 --- a/AFNetworking/AFRESTClient.m +++ b/AFNetworking/AFRESTClient.m @@ -1,4 +1,4 @@ -// AFRestClient.m +// AFRESTClient.m // // Copyright (c) 2011 Gowalla (http://gowalla.com/) // From ebb6eb21ad58d2f52f5fdca5378e8c34c79c06a4 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 22:42:01 -0500 Subject: [PATCH 29/41] You know what's an even _better name? AFHTTPClient. Boom. --- AFNetworking/{AFRESTClient.h => AFHTTPClient.h} | 4 ++-- AFNetworking/{AFRESTClient.m => AFHTTPClient.m} | 8 ++++---- .../AFNetworking Example.xcodeproj/project.pbxproj | 12 ++++++------ Example/Classes/AFGowallaAPIClient.h | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) rename AFNetworking/{AFRESTClient.h => AFHTTPClient.h} (99%) rename AFNetworking/{AFRESTClient.m => AFHTTPClient.m} (99%) diff --git a/AFNetworking/AFRESTClient.h b/AFNetworking/AFHTTPClient.h similarity index 99% rename from AFNetworking/AFRESTClient.h rename to AFNetworking/AFHTTPClient.h index 298fa87..9a0c401 100644 --- a/AFNetworking/AFRESTClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -1,4 +1,4 @@ -// AFRESTClient.h +// AFHTTPClient.h // // Copyright (c) 2011 Gowalla (http://gowalla.com/) // @@ -25,7 +25,7 @@ @protocol AFMultipartFormDataProxy; -@interface AFRESTClient : NSObject { +@interface AFHTTPClient : NSObject { @private NSURL *_baseURL; NSStringEncoding _stringEncoding; diff --git a/AFNetworking/AFRESTClient.m b/AFNetworking/AFHTTPClient.m similarity index 99% rename from AFNetworking/AFRESTClient.m rename to AFNetworking/AFHTTPClient.m index 43279cd..b2a51c3 100644 --- a/AFNetworking/AFRESTClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -1,4 +1,4 @@ -// AFRESTClient.m +// AFHTTPClient.m // // Copyright (c) 2011 Gowalla (http://gowalla.com/) // @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#import "AFRESTClient.h" +#import "AFHTTPClient.h" #import "AFJSONRequestOperation.h" static NSString * const kAFMultipartFormLineDelimiter = @"\r\n"; // CRLF @@ -83,13 +83,13 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, (CFStringRef)kAFLegalCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding)) autorelease]; } -@interface AFRESTClient () +@interface AFHTTPClient () @property (readwrite, nonatomic, retain) NSURL *baseURL; @property (readwrite, nonatomic, retain) NSMutableDictionary *defaultHeaders; @property (readwrite, nonatomic, retain) NSOperationQueue *operationQueue; @end -@implementation AFRESTClient +@implementation AFHTTPClient @synthesize baseURL = _baseURL; @synthesize stringEncoding = _stringEncoding; @synthesize defaultHeaders = _defaultHeaders; diff --git a/Example/AFNetworking Example.xcodeproj/project.pbxproj b/Example/AFNetworking Example.xcodeproj/project.pbxproj index f10cc62..4da83fc 100644 --- a/Example/AFNetworking Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking Example.xcodeproj/project.pbxproj @@ -27,7 +27,7 @@ F8E469671395739D00DB05C8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469661395739D00DB05C8 /* Foundation.framework */; }; F8E469691395739D00DB05C8 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469681395739D00DB05C8 /* CoreGraphics.framework */; }; F8E469DF13957DD500DB05C8 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469DE13957DD500DB05C8 /* CoreLocation.framework */; }; - F8FBFA98142AA239001409DB /* AFRESTClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F8FBFA97142AA238001409DB /* AFRESTClient.m */; }; + F8FBFA98142AA239001409DB /* AFHTTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F8FBFA97142AA238001409DB /* AFHTTPClient.m */; }; FF2B770D140DAC4E00A8DEC2 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FF2B770C140DAC4E00A8DEC2 /* libz.dylib */; }; /* End PBXBuildFile section */ @@ -71,8 +71,8 @@ F8E469E013957DF100DB05C8 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; F8E469E213957DF700DB05C8 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; F8E469E413957E0400DB05C8 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; - F8FBFA96142AA237001409DB /* AFRESTClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFRESTClient.h; path = ../AFNetworking/AFRESTClient.h; sourceTree = ""; }; - F8FBFA97142AA238001409DB /* AFRESTClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFRESTClient.m; path = ../AFNetworking/AFRESTClient.m; sourceTree = ""; }; + F8FBFA96142AA237001409DB /* AFHTTPClient.h */ = {isa = PBXFileReference; fileEncoding = 4; name = AFHTTPClient.h; path = ../AFNetworking/AFHTTPClient.h; sourceTree = ""; }; + F8FBFA97142AA238001409DB /* AFHTTPClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFHTTPClient.m; path = ../AFNetworking/AFHTTPClient.m; sourceTree = ""; }; FF2B770C140DAC4E00A8DEC2 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -227,8 +227,8 @@ F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */, F874B5D413E0AA6500B28E3E /* AFJSONRequestOperation.h */, F874B5CC13E0AA6500B28E3E /* AFJSONRequestOperation.m */, - F8FBFA96142AA237001409DB /* AFRESTClient.h */, - F8FBFA97142AA238001409DB /* AFRESTClient.m */, + F8FBFA96142AA237001409DB /* AFHTTPClient.h */, + F8FBFA97142AA238001409DB /* AFHTTPClient.m */, F874B5D313E0AA6500B28E3E /* AFImageRequestOperation.h */, F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */, F874B5D213E0AA6500B28E3E /* AFImageCache.h */, @@ -336,7 +336,7 @@ F874B5DC13E0AA6500B28E3E /* AFJSONRequestOperation.m in Sources */, F874B5DD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m in Sources */, F874B5E013E0AA6500B28E3E /* UIImageView+AFNetworking.m in Sources */, - F8FBFA98142AA239001409DB /* AFRESTClient.m in Sources */, + F8FBFA98142AA239001409DB /* AFHTTPClient.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/Classes/AFGowallaAPIClient.h b/Example/Classes/AFGowallaAPIClient.h index a744ae0..5fabb8c 100644 --- a/Example/Classes/AFGowallaAPIClient.h +++ b/Example/Classes/AFGowallaAPIClient.h @@ -21,11 +21,11 @@ // THE SOFTWARE. #import -#import "AFRESTClient.h" +#import "AFHTTPClient.h" extern NSString * const kAFGowallaClientID; extern NSString * const kAFGowallaBaseURLString; -@interface AFGowallaAPIClient : AFRESTClient +@interface AFGowallaAPIClient : AFHTTPClient + (AFGowallaAPIClient *)sharedClient; @end From e21a7b5aa1e246d35a8965b703bc8a9de0809bf3 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 23:16:35 -0500 Subject: [PATCH 30/41] Updating and completing documentation for AFHTTPClient --- AFNetworking/AFHTTPClient.h | 102 ++++++++++++++++++++++++++++++------ 1 file changed, 87 insertions(+), 15 deletions(-) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index 9a0c401..0908c75 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -25,6 +25,9 @@ @protocol AFMultipartFormDataProxy; +/** + `AFHTTPClient` objects encapsulates the common patterns of communicating with an application, webservice, or API. It encapsulates persistent information, like base URL, authorization credentials, and HTTP headers, and uses them to construct and manage the execution of HTTP request operations. + */ @interface AFHTTPClient : NSObject { @private NSURL *_baseURL; @@ -44,20 +47,20 @@ @property (nonatomic, assign) NSStringEncoding stringEncoding; /** - The operation queue which manages operations enqueued by the REST client. + The operation queue which manages operations enqueued by the HTTP client. */ @property (readonly, nonatomic, retain) NSOperationQueue *operationQueue;; ///-------------------------------- -/// @name Initializing REST Clients +/// @name Initializing HTTP Clients ///-------------------------------- /** - Initializes an `AFRestClient` object with the specified base URL. + Initializes an `AFHTTPClient` object with the specified base URL. - @param url The base URL for the REST client. This argument must not be nil. + @param url The base URL for the HTTP client. This argument must not be nil. - @return The newly-initialized REST client + @return The newly-initialized HTTP client */ - (id)initWithBaseURL:(NSURL *)url; @@ -66,7 +69,7 @@ ///---------------------------------- /** - Returns the value for the HTTP headers set in request objects created by the REST client + Returns the value for the HTTP headers set in request objects created by the HTTP client @param header The HTTP header to return the default value for @@ -75,7 +78,7 @@ - (NSString *)defaultValueForHeader:(NSString *)header; /** - Sets the value for the HTTP headers set in request objects made by the REST client. If `nil`, removes the existing value for that header. + Sets the value for the HTTP headers set in request objects made by the HTTP client. If `nil`, removes the existing value for that header. @param header The HTTP header to set a default value for @param value The value set as default for the specified header, or `nil @@ -83,7 +86,7 @@ - (void)setDefaultHeader:(NSString *)header value:(NSString *)value; /** - Sets the "Authorization" HTTP header set in request objects made by the REST client to a basic authentication value with Base64-encoded username and password. This overwrites any existing value for this header. + Sets the "Authorization" HTTP header set in request objects made by the HTTP client to a basic authentication value with Base64-encoded username and password. This overwrites any existing value for this header. @param username The HTTP basic auth username @param password The HTTP basic auth password @@ -91,7 +94,7 @@ - (void)setAuthorizationHeaderWithUsername:(NSString *)username password:(NSString *)password; /** - Sets the "Authorization" HTTP header set in request objects made by the REST client to a token-based authentication value, such as an OAuth access token. This overwrites any existing value for this header. + Sets the "Authorization" HTTP header set in request objects made by the HTTP client to a token-based authentication value, such as an OAuth access token. This overwrites any existing value for this header. @param token The authentication token */ @@ -107,10 +110,10 @@ ///------------------------------- /** - Creates an `NSMutableURLRequest` object with the specified HTTP method and resource path. If the HTTP method is `GET`, the parameters will be used to construct a url-encoded query string that is appended to the request's URL. If `POST`, `PUT`, or `DELETE`, the parameters will be encoded into a `application/x-www-form-urlencoded` HTTP body. + Creates an `NSMutableURLRequest` object with the specified HTTP method and path. If the HTTP method is `GET`, the parameters will be used to construct a url-encoded query string that is appended to the request's URL. If `POST`, `PUT`, or `DELETE`, the parameters will be encoded into a `application/x-www-form-urlencoded` HTTP body. @param method The HTTP method for the request, such as `GET`, `POST`, `PUT`, or `DELETE`. - @param path The resource path to be appended to the REST client's base URL and used as the request URL. + @param path The path to be appended to the HTTP client's base URL and used as the request URL. @param parameters The parameters to be either set as a query string for `GET` requests, or the request HTTP body. @return An `NSMutableURLRequest` object @@ -119,10 +122,10 @@ path:(NSString *)path parameters:(NSDictionary *)parameters; /** - Creates an `NSMutableURLRequest` object with the specified HTTP method and resource path, and constructs a `multipart/form-data` HTTP body, using the specified parameters and multipart form data block. + Creates an `NSMutableURLRequest` object with the specified HTTP method and path, and constructs a `multipart/form-data` HTTP body, using the specified parameters and multipart form data block. @param method The HTTP method for the request. Must be either `POST`, `PUT`, or `DELETE`. - @param path The resource path to be appended to the REST client's base URL and used as the request URL. + @param path The path to be appended to the HTTP client's base URL and used as the request URL. @param parameters The parameters to be encoded and set in the request HTTP body. @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormDataProxy` protocol. This can be used to upload files, encode HTTP body as JSON or XML, or specify multiple values for the same parameter, as one might for array values. @@ -141,7 +144,7 @@ ///-------------------------------- /** - Constructs and enqueues an `AFHTTPRequestOperation` to the REST client's operation queue. + Creates and enqueues an `AFHTTPRequestOperation` to the HTTP client's operation queue. @param request The request object to be loaded asynchronously during execution of the operation. @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. @@ -156,7 +159,7 @@ ///--------------------------------- /** - Cancels all operations in the REST client's operation queue that match the specified HTTP method and URL. + Cancels all operations in the HTTP client's operation queue that match the specified HTTP method and URL. @param method The HTTP method to match for the cancelled requests, such as `GET`, `POST`, `PUT`, or `DELETE`. @param url The URL to match for the cancelled requests. @@ -166,21 +169,54 @@ ///--------------------------- /// @name Making HTTP Requests ///--------------------------- + +/** + Creates an `AFHTTPRequestOperation` with a `GET` request, and enqueues it to the HTTP client's operation queue. + + @param path The path to be appended to the HTTP client's base URL and used as the request URL. + @param parameters The parameters to be encoded and appended as the query string for the request URL. + @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. + @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. + */ - (void)getPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success failure:(void (^)(NSError *error))failure; +/** + Creates an `AFHTTPRequestOperation` with a `POST` request, and enqueues it to the HTTP client's operation queue. + + @param path The path to be appended to the HTTP client's base URL and used as the request URL. + @param parameters The parameters to be encoded and set in the request HTTP body. + @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. + @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. + */ - (void)postPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success failure:(void (^)(NSError *error))failure; +/** + Creates an `AFHTTPRequestOperation` with a `PUT` request, and enqueues it to the HTTP client's operation queue. + + @param path The path to be appended to the HTTP client's base URL and used as the request URL. + @param parameters The parameters to be encoded and set in the request HTTP body. + @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. + @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. + */ - (void)putPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success failure:(void (^)(NSError *error))failure; +/** + Creates an `AFHTTPRequestOperation` with a `DELETE` request, and enqueues it to the HTTP client's operation queue. + + @param path The path to be appended to the HTTP client's base URL and used as the request URL. + @param parameters The parameters to be encoded and set in the request HTTP body. + @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. + @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. + */ - (void)deletePath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(id response))success @@ -189,10 +225,46 @@ #pragma mark - +/** + The `AFMultipartFormDataProxy` protocol defines the methods supported by the parameter in the block argument of `multipartFormRequestWithMethod:path:parameters:constructingBodyWithBlock:`. + */ @protocol AFMultipartFormDataProxy + +/** + Appends HTTP headers, followed by the encoded data and the multipart form boundary. + + @param headers The HTTP headers to be appended to the form data. + @param body The data to be encoded and appended to the form data. + */ - (void)appendPartWithHeaders:(NSDictionary *)headers body:(NSData *)body; + +/** + Appends the HTTP header `Content-Disposition: form-data; name=#{name}"`, followed by the encoded data and the multipart form boundary. + + @param data The data to be encoded and appended to the form data. + @param name The name to be associated with the specified data. + */ - (void)appendPartWithFormData:(NSData *)data name:(NSString *)name; + +/** + Appends the HTTP header `Content-Disposition: file; filename=#{filename}"`, followed by the encoded file data and the multipart form boundary. + + @param fileURL The URL for the local file to have its contents appended to the form data. + @param body The filename to be associated with the file contents. If `nil`, the last path component followed by its file extension will be used instead. + */ - (void)appendPartWithFile:(NSURL *)fileURL fileName:(NSString *)fileNameOrNil; + +/** + Appends encoded data to the form data. + + @param data The data to be encoded and appended to the form data. + */ - (void)appendData:(NSData *)data; + +/** + Appends a string to the form data. + + @param string The string to be encoded and appended to the form data. + */ - (void)appendString:(NSString *)string; @end From 4cb29d24ad4e3759144fb90ed0b94e5b60aa94df Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 23:21:41 -0500 Subject: [PATCH 31/41] Adding class description to AFJSONRequestOperation --- AFNetworking/AFJSONRequestOperation.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AFNetworking/AFJSONRequestOperation.h b/AFNetworking/AFJSONRequestOperation.h index bd89943..00fc2b6 100644 --- a/AFNetworking/AFJSONRequestOperation.h +++ b/AFNetworking/AFJSONRequestOperation.h @@ -23,6 +23,9 @@ #import #import "AFHTTPRequestOperation.h" +/** + `AFJSONRequestOperation` is an `NSOperation` that wraps the callback from `AFHTTPRequestOperation` to determine the success or failure of a request based on its status code and response content type, and parse the response body into a JSON object. + */ @interface AFJSONRequestOperation : AFHTTPRequestOperation ///--------------------------------------- From d67db7172ab92f542e41932916752f8f31bce74e Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 23:34:05 -0500 Subject: [PATCH 32/41] Completing documentation of AFImageRequestOperation --- AFNetworking/AFImageRequestOperation.h | 23 +++++++++++++++++++++++ AFNetworking/AFJSONRequestOperation.h | 3 +++ 2 files changed, 26 insertions(+) diff --git a/AFNetworking/AFImageRequestOperation.h b/AFNetworking/AFImageRequestOperation.h index 180c653..2c95678 100644 --- a/AFNetworking/AFImageRequestOperation.h +++ b/AFNetworking/AFImageRequestOperation.h @@ -24,11 +24,34 @@ #import #import "AFHTTPRequestOperation.h" +/** + `AFImageRequestOperation` is an `NSOperation` that wraps the callback from `AFHTTPRequestOperation` to create an image from the response body, and optionally cache the image to memory. + + @see NSOperation + @see AFHTTPRequestOperation + */ @interface AFImageRequestOperation : AFHTTPRequestOperation +/** + Creates and returns an `AFImageRequestOperation` object and sets the specified success callback. + + @param urlRequest The request object to be loaded asynchronously during execution of the operation. + @param success A block object to be executed when the request finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `image/png`). This block has no return value and takes a single arguments, the image created from the response data of the request. + + @return A new image request operation + */ + (AFImageRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest success:(void (^)(UIImage *image))success; +/** + Creates and returns an `AFImageRequestOperation` object and sets the specified success callback. + + @param urlRequest The request object to be loaded asynchronously during execution of the operation. + @param success A block object to be executed when the request finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `image/png`). This block has no return value and takes a three arguments: the request object of the operation, the response for the request, and the image created from the response data. + @param success A block object to be executed when the request finishes unsuccessfully. This block has no return value and takes a three arguments: the request object of the operation, the response for the request, and the error associated with the cause for the unsuccessful operation. + + @return A new image request operation + */ + (AFImageRequestOperation *)operationWithRequest:(NSURLRequest *)urlRequest imageProcessingBlock:(UIImage *(^)(UIImage *))imageProcessingBlock cacheName:(NSString *)cacheNameOrNil diff --git a/AFNetworking/AFJSONRequestOperation.h b/AFNetworking/AFJSONRequestOperation.h index 00fc2b6..057defd 100644 --- a/AFNetworking/AFJSONRequestOperation.h +++ b/AFNetworking/AFJSONRequestOperation.h @@ -25,6 +25,9 @@ /** `AFJSONRequestOperation` is an `NSOperation` that wraps the callback from `AFHTTPRequestOperation` to determine the success or failure of a request based on its status code and response content type, and parse the response body into a JSON object. + + @see NSOperation + @see AFHTTPRequestOperation */ @interface AFJSONRequestOperation : AFHTTPRequestOperation From 2a8cce88a5e156bd9c88d2c1c39fdc57915ffec6 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Wed, 21 Sep 2011 23:46:00 -0500 Subject: [PATCH 33/41] Changing AFImageCache APIs to use URLs rather than NSURLRequests Completing documentation for AFImageCache --- AFNetworking/AFImageCache.h | 31 ++++++++++++++++++++++--- AFNetworking/AFImageCache.m | 14 +++++------ AFNetworking/AFImageRequestOperation.m | 2 +- AFNetworking/UIImageView+AFNetworking.m | 2 +- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/AFNetworking/AFImageCache.h b/AFNetworking/AFImageCache.h index f85a48f..08d9e3f 100644 --- a/AFNetworking/AFImageCache.h +++ b/AFNetworking/AFImageCache.h @@ -23,15 +23,40 @@ #import #import "AFImageRequestOperation.h" +/** + `AFImageCache` is a subclass of `NSCache` that stores and retrieves images from cache. + + @discussion `AFImageCache` is used to cache images for successful `AFImageRequestOperations` with the proper cache policy. + */ @interface AFImageCache : NSCache +/** + Returns the shared image cache object for the system. + + @return The systemwide image cache. + */ + (AFImageCache *)sharedImageCache; -- (UIImage *)cachedImageForRequest:(NSURLRequest *)urlRequest - cacheName:(NSString *)cacheName; +/** + Returns the image associated with a given URL and cache name. + + @param url The URL associated with the image in the cache. + @param cacheName The cache name associated with the image in the cache. This allows for multiple versions of an image to be associated for a single URL, such as image thumbnails, for instance. + + @return The image associated with the URL and cache name, or `nil` if not image exists. + */ +- (UIImage *)cachedImageForURL:(NSURL *)url + cacheName:(NSString *)cacheName; +/** + Stores an image into cache, associated with a given URL and cache name. + + @param image The image to be stored in cache. + @param url The URL to be associated with the image. + @param cacheName The cache name to be associated with the image in the cache. This allows for multiple versions of an image to be associated for a single URL, such as image thumbnails, for instance. + */ - (void)cacheImage:(UIImage *)image - forRequest:(NSURLRequest *)urlRequest + forURL:(NSURL *)url cacheName:(NSString *)cacheName; @end diff --git a/AFNetworking/AFImageCache.m b/AFNetworking/AFImageCache.m index 968b574..de74346 100644 --- a/AFNetworking/AFImageCache.m +++ b/AFNetworking/AFImageCache.m @@ -22,8 +22,8 @@ #import "AFImageCache.h" -static inline NSString * AFImageCacheKey(NSURLRequest *urlRequest, NSString *cacheName) { - return [[[urlRequest URL] absoluteString] stringByAppendingFormat:@"#%@", cacheName]; +static inline NSString * AFImageCacheKeyFromURLAndCacheName(NSURL *url, NSString *cacheName) { + return [[url absoluteString] stringByAppendingFormat:@"#%@", cacheName]; } @implementation AFImageCache @@ -39,21 +39,21 @@ static inline NSString * AFImageCacheKey(NSURLRequest *urlRequest, NSString *cac return _sharedImageCache; } -- (UIImage *)cachedImageForRequest:(NSURLRequest *)urlRequest - cacheName:(NSString *)cacheName +- (UIImage *)cachedImageForURL:(NSURL *)url + cacheName:(NSString *)cacheName { - return [self objectForKey:AFImageCacheKey(urlRequest, cacheName)]; + return [self objectForKey:AFImageCacheKeyFromURLAndCacheName(url, cacheName)]; } - (void)cacheImage:(UIImage *)image - forRequest:(NSURLRequest *)urlRequest + forURL:(NSURL *)url cacheName:(NSString *)cacheName { if (!image) { return; } - [self setObject:image forKey:AFImageCacheKey(urlRequest, cacheName)]; + [self setObject:image forKey:AFImageCacheKeyFromURLAndCacheName(url, cacheName)]; } @end diff --git a/AFNetworking/AFImageRequestOperation.m b/AFNetworking/AFImageRequestOperation.m index c2d5cf5..98867e8 100644 --- a/AFNetworking/AFImageRequestOperation.m +++ b/AFNetworking/AFImageRequestOperation.m @@ -77,7 +77,7 @@ static dispatch_queue_t image_request_operation_processing_queue() { } }); - [[AFImageCache sharedImageCache] cacheImage:image forRequest:request cacheName:cacheNameOrNil]; + [[AFImageCache sharedImageCache] cacheImage:image forURL:[request URL] cacheName:cacheNameOrNil]; } }); }]; diff --git a/AFNetworking/UIImageView+AFNetworking.m b/AFNetworking/UIImageView+AFNetworking.m index 7140fd5..dcd3a50 100644 --- a/AFNetworking/UIImageView+AFNetworking.m +++ b/AFNetworking/UIImageView+AFNetworking.m @@ -120,7 +120,7 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp cacheName = [cacheName stringByAppendingFormat:@"(%@)", NSStringFromCGSize(placeholderImage.size)]; } - UIImage *cachedImage = [[AFImageCache sharedImageCache] cachedImageForRequest:urlRequest cacheName:cacheName]; + UIImage *cachedImage = [[AFImageCache sharedImageCache] cachedImageForURL:[urlRequest URL] cacheName:cacheName]; if (cachedImage) { self.image = cachedImage; From 2dd68212c0e4712874cbc9bfc4e56aa08036f539 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 22 Sep 2011 09:43:58 -0500 Subject: [PATCH 34/41] Adding +clientWithBaseURL: Noting that initWithBaseURL: is the designated initializer --- AFNetworking/AFHTTPClient.h | 17 ++++++++++++++--- AFNetworking/AFHTTPClient.m | 4 ++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index 0908c75..7452ed7 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -51,15 +51,26 @@ */ @property (readonly, nonatomic, retain) NSOperationQueue *operationQueue;; -///-------------------------------- -/// @name Initializing HTTP Clients -///-------------------------------- +///--------------------------------------------- +/// @name Creating and Initializing HTTP Clients +///--------------------------------------------- + +/** + Creates and initializes an `AFHTTPClient` object with the specified base URL. + + @param url The base URL for the HTTP client. This argument must not be nil. + + @return The newly-initialized HTTP client + */ ++ (AFHTTPClient *)clientWithBaseURL:(NSURL *)url; /** Initializes an `AFHTTPClient` object with the specified base URL. @param url The base URL for the HTTP client. This argument must not be nil. + @discussion This is the designated initializer for `AFHTTPClient` + @return The newly-initialized HTTP client */ - (id)initWithBaseURL:(NSURL *)url; diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index b2a51c3..9ba7613 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -95,6 +95,10 @@ static NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSS @synthesize defaultHeaders = _defaultHeaders; @synthesize operationQueue = _operationQueue; ++ (AFHTTPClient *)clientWithBaseURL:(NSURL *)url { + return [[[self alloc] initWithBaseURL:url] autorelease]; +} + - (id)initWithBaseURL:(NSURL *)url { self = [super init]; if (!self) { From 95ca172d9d3e00cf7f5ede39b740eec94ef864d7 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 22 Sep 2011 10:25:07 -0500 Subject: [PATCH 35/41] Fixing API call for spots in the example app --- Example/Classes/Controllers/NearbySpotsViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/Classes/Controllers/NearbySpotsViewController.m b/Example/Classes/Controllers/NearbySpotsViewController.m index 3c5aecc..08b4069 100644 --- a/Example/Classes/Controllers/NearbySpotsViewController.m +++ b/Example/Classes/Controllers/NearbySpotsViewController.m @@ -70,7 +70,7 @@ [self.activityIndicatorView startAnimating]; self.navigationItem.rightBarButtonItem.enabled = NO; - [Spot spotsWithURLString:@"/spots/advanced_search" near:location parameters:[NSDictionary dictionaryWithObject:@"128" forKey:@"per_page"] block:^(NSArray *records) { + [Spot spotsWithURLString:@"/spots" 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]; From c84ca99269b4a02c63367c6f59a2611195a913c2 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 22 Sep 2011 10:25:55 -0500 Subject: [PATCH 36/41] Adding documentation for AFNetworkActivityIndicatorManager Changing public API for AFNetworkActivityIndicatorManager from -start/stopAnimating to -increment/decrementActivityCount --- AFNetworking/AFHTTPRequestOperation.m | 4 ++-- .../AFNetworkActivityIndicatorManager.h | 19 +++++++++++++++++-- .../AFNetworkActivityIndicatorManager.m | 4 ++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/AFNetworking/AFHTTPRequestOperation.m b/AFNetworking/AFHTTPRequestOperation.m index af4c841..11eb2c2 100644 --- a/AFNetworking/AFHTTPRequestOperation.m +++ b/AFNetworking/AFHTTPRequestOperation.m @@ -227,11 +227,11 @@ static NSThread *_networkRequestThread = nil; switch (state) { case AFHTTPOperationExecutingState: - [[AFNetworkActivityIndicatorManager sharedManager] startAnimating]; + [[AFNetworkActivityIndicatorManager sharedManager] incrementActivityCount]; [[NSNotificationCenter defaultCenter] postNotificationName:AFHTTPOperationDidStartNotification object:self]; break; case AFHTTPOperationFinishedState: - [[AFNetworkActivityIndicatorManager sharedManager] stopAnimating]; + [[AFNetworkActivityIndicatorManager sharedManager] decrementActivityCount]; [[NSNotificationCenter defaultCenter] postNotificationName:AFHTTPOperationDidFinishNotification object:self]; break; default: diff --git a/AFNetworking/AFNetworkActivityIndicatorManager.h b/AFNetworking/AFNetworkActivityIndicatorManager.h index f5366e4..59110b9 100644 --- a/AFNetworking/AFNetworkActivityIndicatorManager.h +++ b/AFNetworking/AFNetworkActivityIndicatorManager.h @@ -22,14 +22,29 @@ #import +/** + `AFNetworkActivityIndicatorManager` manages the state of the network activity indicator in the status bar. When network operations start, they can call `-incrementActivityCount`, and once they're finished, call `-decrementActivityCount`. The number of active requests is incremented and decremented much like a stack or a semaphore, and the activity indicator will animate so long as that number is greater than zero. + */ @interface AFNetworkActivityIndicatorManager : NSObject { @private NSInteger _activityCount; } +/** + Returns the shared network activity indicator manager object for the system. + + @return The systemwide network activity indicator manager. + */ + (AFNetworkActivityIndicatorManager *)sharedManager; -- (void)startAnimating; -- (void)stopAnimating; +/** + Increments the number of active network requests. If this number was zero before incrementing, this will start animating the status bar network activity indicator. + */ +- (void)incrementActivityCount; + +/** + Decrements the number of active network requests. If this number becomes zero before decrementing, this will stop animating the status bar network activity indicator. + */ +- (void)decrementActivityCount; @end diff --git a/AFNetworking/AFNetworkActivityIndicatorManager.m b/AFNetworking/AFNetworkActivityIndicatorManager.m index 17f4d18..89d12cb 100644 --- a/AFNetworking/AFNetworkActivityIndicatorManager.m +++ b/AFNetworking/AFNetworkActivityIndicatorManager.m @@ -47,13 +47,13 @@ [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:self.activityCount > 0]; } -- (void)startAnimating { +- (void)incrementActivityCount { @synchronized(self) { self.activityCount += 1; } } -- (void)stopAnimating { +- (void)decrementActivityCount { @synchronized(self) { self.activityCount -= 1; } From eebc763f7f3987bdd222357ca70e0df6ec9d9e63 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 22 Sep 2011 11:30:13 -0500 Subject: [PATCH 37/41] Adding documentation to UIImageView category Changing API for setImageWithURLRequest:placeholderImage:success to setImageWithURLRequest:placeholderImage:success:failure --- AFNetworking/UIImageView+AFNetworking.h | 36 ++++++++++++++++++++++++- AFNetworking/UIImageView+AFNetworking.m | 19 ++++++++----- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/AFNetworking/UIImageView+AFNetworking.h b/AFNetworking/UIImageView+AFNetworking.h index 16f8889..4b6d72b 100644 --- a/AFNetworking/UIImageView+AFNetworking.h +++ b/AFNetworking/UIImageView+AFNetworking.h @@ -23,16 +23,50 @@ #import #import "AFImageRequestOperation.h" +/** + This category adds methods to the UIKit framework's `UIImageView` class. The methods in this category provide support for loading remote images asynchronously from a URL. + */ @interface UIImageView (AFNetworking) +/** + Creates and enqueues an image request operation, which asynchronously downloads the image from the specified URL, and sets it the request is finished. If the image is cached locally, the image is set immediately, otherwise, the image is set once the request is finished. + + @discussion By default, url requests have a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set to use HTTP pipelining, and not handle cookies. To configure url requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` + + @param url The URL used for the image request. + */ - (void)setImageWithURL:(NSURL *)url; +/** + Creates and enqueues an image request operation, which asynchronously downloads the image from the specified URL. If the image is cached locally, the image is set immediately. Otherwise, the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. + + @param url The URL used for the image request. + @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. + + @discussion By default, url requests have a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set to use HTTP pipelining, and not handle cookies. To configure url requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` + + @warning If `placeholderImage` is specified, the remote image will be resized to the dimensions of the placeholder image before being set. + */ - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage; +/** + Creates and enqueues an image request operation, which asynchronously downloads the image with the specified url request object. If the image is cached locally, the image is set immediately. Otherwise, the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. + + @param urlRequest The url request used for the image request. + @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. + @param success A block to be executed when the image request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content type (e.g. `image/png`). This block has no return value and takes three arguments, the request sent from the client, the response received from the server, and the image created from the response data of request. If the image was returned from cache, the request and response parameters will be `nil`. + @param failure A block object to be executed when the image request operation finishes unsuccessfully, or that finishes successfully. This block has no return value and takes three arguments, the request sent from the client, the response received from the server, and the error object describing the network or parsing error that occurred. + + + @discussion By default, url requests have a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set to use HTTP pipelining, and not handle cookies. To configure url requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` + + @warning If `placeholderImage` is specified, the remote image will be resized to the dimensions of the placeholder image before being set. + */ - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest placeholderImage:(UIImage *)placeholderImage - success:(void (^)(UIImage *image, BOOL cacheUsed))success; + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response,UIImage *image))success + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; - (void)cancelImageRequestOperation; diff --git a/AFNetworking/UIImageView+AFNetworking.m b/AFNetworking/UIImageView+AFNetworking.m index dcd3a50..32a3826 100644 --- a/AFNetworking/UIImageView+AFNetworking.m +++ b/AFNetworking/UIImageView+AFNetworking.m @@ -102,12 +102,13 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp [request setHTTPShouldHandleCookies:NO]; [request setHTTPShouldUsePipelining:YES]; - [self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil]; + [self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil failure:nil]; } - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest placeholderImage:(UIImage *)placeholderImage - success:(void (^)(UIImage *image, BOOL cacheUsed))success + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response,UIImage *image))success + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure { if (![urlRequest URL] || (![self.imageRequestOperation isCancelled] && [[urlRequest URL] isEqual:self.imageRequestOperation.request.URL])) { return; @@ -125,7 +126,7 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp self.image = cachedImage; if (success) { - success(cachedImage, YES); + success(nil, nil, cachedImage); } } else { self.image = placeholderImage; @@ -140,7 +141,7 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp if (self.imageRequestOperation && ![self.imageRequestOperation isCancelled]) { dispatch_async(dispatch_get_main_queue(), ^{ if (success) { - success(image, NO); + success(request, response, image); } if ([[request URL] isEqual:[[self.imageRequestOperation request] URL]]) { @@ -152,11 +153,15 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp } } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) { self.imageRequestOperation = nil; + + dispatch_async(dispatch_get_main_queue(), ^{ + if (failure) { + failure(request, response, error); + } + }); }]; - if ([urlRequest cachePolicy] != NSURLCacheStorageNotAllowed) { - [[[self class] sharedImageRequestOperationQueue] addOperation:self.imageRequestOperation]; - } + [[[self class] sharedImageRequestOperationQueue] addOperation:self.imageRequestOperation]; } } From 7a2cad0a566663878b81195b647771dcef1e44a5 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 22 Sep 2011 11:31:01 -0500 Subject: [PATCH 38/41] Minor revisions to documentation, mostly around style and conventions --- AFNetworking/AFHTTPClient.h | 10 +++++----- AFNetworking/AFHTTPRequestOperation.h | 8 ++++---- AFNetworking/AFImageRequestOperation.h | 6 +++--- AFNetworking/AFImageRequestOperation.m | 4 +++- AFNetworking/AFJSONRequestOperation.h | 10 +++++----- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index 7452ed7..4fd94a1 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -158,7 +158,7 @@ Creates and enqueues an `AFHTTPRequestOperation` to the HTTP client's operation queue. @param request The request object to be loaded asynchronously during execution of the operation. - @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. + @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content type (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. */ - (void)enqueueHTTPOperationWithRequest:(NSURLRequest *)request @@ -186,7 +186,7 @@ @param path The path to be appended to the HTTP client's base URL and used as the request URL. @param parameters The parameters to be encoded and appended as the query string for the request URL. - @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. + @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content type (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. */ - (void)getPath:(NSString *)path @@ -199,7 +199,7 @@ @param path The path to be appended to the HTTP client's base URL and used as the request URL. @param parameters The parameters to be encoded and set in the request HTTP body. - @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. + @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content type (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. */ - (void)postPath:(NSString *)path @@ -212,7 +212,7 @@ @param path The path to be appended to the HTTP client's base URL and used as the request URL. @param parameters The parameters to be encoded and set in the request HTTP body. - @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. + @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content type (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. */ - (void)putPath:(NSString *)path @@ -225,7 +225,7 @@ @param path The path to be appended to the HTTP client's base URL and used as the request URL. @param parameters The parameters to be encoded and set in the request HTTP body. - @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. + @param success A block object to be executed when the request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content type (e.g. `application/json`). This block has no return value and takes a single argument, which is the response object created from the response data of request. @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. */ - (void)deletePath:(NSString *)path diff --git a/AFNetworking/AFHTTPRequestOperation.h b/AFNetworking/AFHTTPRequestOperation.h index 6072e3c..f152daa 100644 --- a/AFNetworking/AFHTTPRequestOperation.h +++ b/AFNetworking/AFHTTPRequestOperation.h @@ -87,7 +87,7 @@ extern NSString * const AFHTTPOperationDidFinishNotification; Creates and returns an `AFHTTPRequestOperation` object and sets the specified completion callback. @param urlRequest The request object to be loaded asynchronously during execution of the operation. - @param completion A block object to be executed when the HTTP request operation is finished. This block has no return value and takes four arguments: the NSURLRequest sent from the client and the NSHTTPURLResponse received from the server, the NSData received by the server during the execution of the request, and an NSError, which will have been set if an error occured while loading the request. + @param completion A block object to be executed when the HTTP request operation is finished. This block has no return value and takes four arguments: the request sent from the client, the response received from the server, the HTTP body received by the server during the execution of the request, and an error, which will have been set if an error occured while loading the request. @see operationWithRequest:inputStream:outputStream:completion @@ -101,8 +101,8 @@ extern NSString * const AFHTTPOperationDidFinishNotification; @param urlRequest The request object to be loaded asynchronously during execution of the operation. @param inputStream The input stream object for reading data to be sent during the request. If set, the input stream is set as the HTTPBodyStream on the NSMutableURLRequest, and the request method is changed to `POST`. This argument may be `nil`. - @param outputStream The output stream object for writing data received during the request. If set, data accumulated in NSURLConnectionDelegate methods will be sent to the output stream, and the NSData parameter in the completion block will be `nil`. This argument may be `nil`. - @param completion A block object to be executed when the HTTP request operation is finished. This block has no return value and takes four arguments: the NSURLRequest sent from the client and the NSHTTPURLResponse received from the server, the NSData received by the server during the execution of the request, and an NSError, which will have been set if an error occured while loading the request. This argument may be `NULL`. + @param outputStream The output stream object for writing data received during the request. If set, data accumulated in `NSURLConnectionDelegate` methods will be sent to the output stream, and the NSData parameter in the completion block will be `nil`. This argument may be `nil`. + @param completion A block object to be executed when the HTTP request operation is finished. This block has no return value and takes four arguments: the request sent from the client, the response received from the server, the NSData received by the server during the execution of the request, and an error, which will have been set if an error occured while loading the request. This argument may be `nil`. @see operationWithRequest:completion @@ -129,7 +129,7 @@ extern NSString * const AFHTTPOperationDidFinishNotification; /** Sets a callback to be called when an undetermined number of bytes have been uploaded to the server. - @param block A block object to be called when an undetermined number of bytes have been uploaded to the server. This block has no return value and takes two arguments: the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the NSHTTPURLResponse. This block may be called multiple times. + @param block A block object to be called when an undetermined number of bytes have been uploaded to the server. This block has no return value and takes two arguments: the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times. @see setUploadProgressBlock */ diff --git a/AFNetworking/AFImageRequestOperation.h b/AFNetworking/AFImageRequestOperation.h index 2c95678..883544c 100644 --- a/AFNetworking/AFImageRequestOperation.h +++ b/AFNetworking/AFImageRequestOperation.h @@ -36,7 +36,7 @@ Creates and returns an `AFImageRequestOperation` object and sets the specified success callback. @param urlRequest The request object to be loaded asynchronously during execution of the operation. - @param success A block object to be executed when the request finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `image/png`). This block has no return value and takes a single arguments, the image created from the response data of the request. + @param success A block object to be executed when the request finishes successfully, with a status code in the 2xx range, and with an acceptable content type (e.g. `image/png`). This block has no return value and takes a single arguments, the image created from the response data of the request. @return A new image request operation */ @@ -47,8 +47,8 @@ Creates and returns an `AFImageRequestOperation` object and sets the specified success callback. @param urlRequest The request object to be loaded asynchronously during execution of the operation. - @param success A block object to be executed when the request finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `image/png`). This block has no return value and takes a three arguments: the request object of the operation, the response for the request, and the image created from the response data. - @param success A block object to be executed when the request finishes unsuccessfully. This block has no return value and takes a three arguments: the request object of the operation, the response for the request, and the error associated with the cause for the unsuccessful operation. + @param success A block object to be executed when the request finishes successfully, with a status code in the 2xx range, and with an acceptable content type (e.g. `image/png`). This block has no return value and takes a three arguments: the request object of the operation, the response for the request, and the image created from the response data. + @param failure A block object to be executed when the request finishes unsuccessfully. This block has no return value and takes a three arguments: the request object of the operation, the response for the request, and the error associated with the cause for the unsuccessful operation. @return A new image request operation */ diff --git a/AFNetworking/AFImageRequestOperation.m b/AFNetworking/AFImageRequestOperation.m index 98867e8..0e4d702 100644 --- a/AFNetworking/AFImageRequestOperation.m +++ b/AFNetworking/AFImageRequestOperation.m @@ -77,7 +77,9 @@ static dispatch_queue_t image_request_operation_processing_queue() { } }); - [[AFImageCache sharedImageCache] cacheImage:image forURL:[request URL] cacheName:cacheNameOrNil]; + if ([request cachePolicy] != NSURLCacheStorageNotAllowed) { + [[AFImageCache sharedImageCache] cacheImage:image forURL:[request URL] cacheName:cacheNameOrNil]; + } } }); }]; diff --git a/AFNetworking/AFJSONRequestOperation.h b/AFNetworking/AFJSONRequestOperation.h index 057defd..f7b44b7 100644 --- a/AFNetworking/AFJSONRequestOperation.h +++ b/AFNetworking/AFJSONRequestOperation.h @@ -39,7 +39,7 @@ Creates and returns an `AFJSONRequestOperation` object and sets the specified success callback. @param urlRequest The request object to be loaded asynchronously during execution of the operation - @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request, or nil if there was an error. + @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content type (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request, or nil if there was an error. @see defaultAcceptableStatusCodes @see defaultAcceptableContentTypes @@ -54,8 +54,8 @@ Creates and returns an `AFJSONRequestOperation` object and sets the specified success and failure callbacks. @param urlRequest The request object to be loaded asynchronously during execution of the operation - @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request. - @param failure A block object to be executed when the JSON request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. + @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content type (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request. + @param failure A block object to be executed when the JSON request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the error describing the network or parsing error that occurred. @see defaultAcceptableStatusCodes @see defaultAcceptableContentTypes @@ -73,8 +73,8 @@ @param urlRequest The request object to be loaded asynchronously during execution of the operation @param acceptableStatusCodes An `NSIndexSet` object that specifies the ranges of acceptable status codes. If you specify nil, all status codes will be considered acceptable. @param acceptableContentTypes An `NSSet` object that specifies the acceptable content types. If you specify nil, all content types will be considered acceptable. - @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content types (e.g. `application/json`). This block has no return value and takes a single argument, which is the JSON object created from the response data of request. - @param failure A block object to be executed when the JSON request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes a single argument, which is the `NSError` object describing the network or parsing error that occurred. + @param success A block object to be executed when the JSON request operation finishes successfully, with a status code in the 2xx range, and with an acceptable content type (e.g. `application/json`). This block has no return value and takes three arguments, the request sent from the client, the response received from the server, and the JSON object created from the response data of request. + @param failure A block object to be executed when the JSON request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data as JSON. This block has no return value and takes three arguments, the request sent from the client, the response received from the server, and the error describing the network or parsing error that occurred. @return A new JSON request operation */ From 42da37a5a3ed00991aff7cf6f0a0af3a93406ab6 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 22 Sep 2011 11:42:48 -0500 Subject: [PATCH 39/41] Namespacing private methods in UIImageView category --- AFNetworking/UIImageView+AFNetworking.m | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/AFNetworking/UIImageView+AFNetworking.m b/AFNetworking/UIImageView+AFNetworking.m index 32a3826..d03c178 100644 --- a/AFNetworking/UIImageView+AFNetworking.m +++ b/AFNetworking/UIImageView+AFNetworking.m @@ -59,26 +59,26 @@ static UIImage * AFImageByScalingAndCroppingImageToSize(UIImage *image, CGSize s static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOperation"; @interface UIImageView (_AFNetworking) -@property (readwrite, nonatomic, retain) AFImageRequestOperation *imageRequestOperation; +@property (readwrite, nonatomic, retain, setter = af_setImageRequestOperation:) AFImageRequestOperation *af_imageRequestOperation; @end @implementation UIImageView (_AFNetworking) -@dynamic imageRequestOperation; +@dynamic af_imageRequestOperation; @end #pragma mark - @implementation UIImageView (AFNetworking) -- (AFHTTPRequestOperation *)imageRequestOperation { +- (AFHTTPRequestOperation *)af_imageRequestOperation { return (AFHTTPRequestOperation *)objc_getAssociatedObject(self, kUIImageViewImageRequestObjectKey); } -- (void)setImageRequestOperation:(AFImageRequestOperation *)imageRequestOperation { +- (void)af_setImageRequestOperation:(AFImageRequestOperation *)imageRequestOperation { objc_setAssociatedObject(self, kUIImageViewImageRequestObjectKey, imageRequestOperation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } -+ (NSOperationQueue *)sharedImageRequestOperationQueue { ++ (NSOperationQueue *)af_sharedImageRequestOperationQueue { static NSOperationQueue *_imageRequestOperationQueue = nil; if (!_imageRequestOperationQueue) { @@ -110,7 +110,7 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response,UIImage *image))success failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure { - if (![urlRequest URL] || (![self.imageRequestOperation isCancelled] && [[urlRequest URL] isEqual:self.imageRequestOperation.request.URL])) { + if (![urlRequest URL] || (![self.af_imageRequestOperation isCancelled] && [[urlRequest URL] isEqual:self.af_imageRequestOperation.request.URL])) { return; } else { [self cancelImageRequestOperation]; @@ -131,20 +131,20 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp } else { self.image = placeholderImage; - self.imageRequestOperation = [AFImageRequestOperation operationWithRequest:urlRequest imageProcessingBlock:^UIImage *(UIImage *image) { + self.af_imageRequestOperation = [AFImageRequestOperation operationWithRequest:urlRequest imageProcessingBlock:^UIImage *(UIImage *image) { if (placeholderImage) { image = AFImageByScalingAndCroppingImageToSize(image, placeholderImage.size); } return image; } cacheName:cacheName success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { - if (self.imageRequestOperation && ![self.imageRequestOperation isCancelled]) { + if (self.af_imageRequestOperation && ![self.af_imageRequestOperation isCancelled]) { dispatch_async(dispatch_get_main_queue(), ^{ if (success) { success(request, response, image); } - if ([[request URL] isEqual:[[self.imageRequestOperation request] URL]]) { + if ([[request URL] isEqual:[[self.af_imageRequestOperation request] URL]]) { self.image = image; } else { self.image = placeholderImage; @@ -152,7 +152,7 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp }); } } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) { - self.imageRequestOperation = nil; + self.af_imageRequestOperation = nil; dispatch_async(dispatch_get_main_queue(), ^{ if (failure) { @@ -161,12 +161,12 @@ static NSString * const kUIImageViewImageRequestObjectKey = @"_af_imageRequestOp }); }]; - [[[self class] sharedImageRequestOperationQueue] addOperation:self.imageRequestOperation]; + [[[self class] af_sharedImageRequestOperationQueue] addOperation:self.af_imageRequestOperation]; } } - (void)cancelImageRequestOperation { - [self.imageRequestOperation cancel]; + [self.af_imageRequestOperation cancel]; } @end From ba4470ed136bd3ad6c6eb279a6639dd83d72cc1a Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 22 Sep 2011 11:58:35 -0500 Subject: [PATCH 40/41] Use imperial system based on current locale --- Example/Classes/Controllers/NearbySpotsViewController.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Example/Classes/Controllers/NearbySpotsViewController.m b/Example/Classes/Controllers/NearbySpotsViewController.m index 08b4069..c21c654 100644 --- a/Example/Classes/Controllers/NearbySpotsViewController.m +++ b/Example/Classes/Controllers/NearbySpotsViewController.m @@ -159,7 +159,9 @@ static TTTLocationFormatter *_locationFormatter = nil; if (!_locationFormatter) { _locationFormatter = [[TTTLocationFormatter alloc] init]; - [_locationFormatter setUnitSystem:TTTImperialSystem]; + if (![[[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem] boolValue]) { + [_locationFormatter setUnitSystem:TTTImperialSystem]; + } } if (self.locationManager.location) { From 29c25bb52e56cb9be5ec08a9b7013f041ebea146 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Thu, 22 Sep 2011 12:04:23 -0500 Subject: [PATCH 41/41] Fixing unnecessary semicolon compiler warning in TTTLocationFormatter --- Example/Vendor/TTT/TTTLocationFormatter.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Example/Vendor/TTT/TTTLocationFormatter.m b/Example/Vendor/TTT/TTTLocationFormatter.m index 46894b8..ff40065 100644 --- a/Example/Vendor/TTT/TTTLocationFormatter.m +++ b/Example/Vendor/TTT/TTTLocationFormatter.m @@ -47,11 +47,11 @@ static inline double CLLocationDistanceToMiles(CLLocationDistance distance) { static inline double DEG2RAD(double degrees) { return degrees * M_PI / 180; -}; +} static inline double RAD2DEG(double radians) { return radians * 180 / M_PI; -}; +} static inline CLLocationDegrees CLLocationDegreesBearingBetweenCoordinates(CLLocationCoordinate2D originCoordinate, CLLocationCoordinate2D destinationCoordinate) { double lat1 = DEG2RAD(originCoordinate.latitude);