|
@@ -1,17 +1,17 @@
|
|
|
// AFHTTPClient.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
|
|
@@ -40,11 +40,9 @@
|
|
|
#import <netdb.h>
|
|
|
#endif
|
|
|
|
|
|
-NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change";
|
|
|
-
|
|
|
@interface AFMultipartFormData : NSObject <AFMultipartFormData>
|
|
|
|
|
|
-- (id)initWithURLRequest:(NSMutableURLRequest *)request
|
|
|
+- (id)initWithURLRequest:(NSMutableURLRequest *)request
|
|
|
stringEncoding:(NSStringEncoding)encoding;
|
|
|
|
|
|
- (NSMutableURLRequest *)requestByFinalizingMultipartFormData;
|
|
@@ -54,6 +52,9 @@ NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire
|
|
|
#pragma mark -
|
|
|
|
|
|
#ifdef _SYSTEMCONFIGURATION_H
|
|
|
+NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change";
|
|
|
+NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem";
|
|
|
+
|
|
|
typedef SCNetworkReachabilityRef AFNetworkReachabilityRef;
|
|
|
typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status);
|
|
|
#else
|
|
@@ -62,8 +63,6 @@ typedef id AFNetworkReachabilityRef;
|
|
|
|
|
|
typedef void (^AFCompletionBlock)(void);
|
|
|
|
|
|
-static NSUInteger const kAFHTTPClientDefaultMaxConcurrentOperationCount = 4;
|
|
|
-
|
|
|
static NSString * AFBase64EncodedStringFromString(NSString *string) {
|
|
|
NSData *data = [NSData dataWithBytes:[string UTF8String] length:[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
|
|
|
NSUInteger length = [data length];
|
|
@@ -77,7 +76,7 @@ static NSString * AFBase64EncodedStringFromString(NSString *string) {
|
|
|
for (NSUInteger j = i; j < (i + 3); j++) {
|
|
|
value <<= 8;
|
|
|
if (j < length) {
|
|
|
- value |= (0xFF & input[j]);
|
|
|
+ value |= (0xFF & input[j]);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -93,91 +92,78 @@ static NSString * AFBase64EncodedStringFromString(NSString *string) {
|
|
|
return [[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding];
|
|
|
}
|
|
|
|
|
|
-NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
|
|
|
- static NSString * const kAFLegalCharactersToBeEscaped = @"?!@#$^&%*+=,:;'\"`<>()[]{}/\\|~ ";
|
|
|
+static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
|
|
|
+ // Escape characters that are legal in URIs, but have unintentional semantic significance when used in a query string parameter
|
|
|
+ static NSString * const kAFLegalCharactersToBeEscaped = @":/.?&=;+!@$()~";
|
|
|
|
|
|
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, (__bridge CFStringRef)kAFLegalCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding));
|
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
-@interface AFQueryStringComponent : NSObject
|
|
|
+@interface AFQueryStringPair : NSObject
|
|
|
+@property (readwrite, nonatomic, retain) id field;
|
|
|
+@property (readwrite, nonatomic, retain) id value;
|
|
|
|
|
|
-@property (readwrite, nonatomic) id key;
|
|
|
-@property (readwrite, nonatomic) id value;
|
|
|
-
|
|
|
-- (id)initWithKey:(id)key value:(id)value;
|
|
|
+- (id)initWithField:(id)field value:(id)value;
|
|
|
- (NSString *)URLEncodedStringValueWithEncoding:(NSStringEncoding)stringEncoding;
|
|
|
|
|
|
@end
|
|
|
|
|
|
-@implementation AFQueryStringComponent
|
|
|
-@synthesize key = _key;
|
|
|
+@implementation AFQueryStringPair
|
|
|
+@synthesize field = _field;
|
|
|
@synthesize value = _value;
|
|
|
|
|
|
-- (id)initWithKey:(id)key value:(id)value {
|
|
|
+- (id)initWithField:(id)field value:(id)value {
|
|
|
self = [super init];
|
|
|
if (!self) {
|
|
|
return nil;
|
|
|
}
|
|
|
-
|
|
|
- _key = key;
|
|
|
- _value = value;
|
|
|
+
|
|
|
+ self.field = field;
|
|
|
+ self.value = value;
|
|
|
|
|
|
return self;
|
|
|
}
|
|
|
|
|
|
- (NSString *)URLEncodedStringValueWithEncoding:(NSStringEncoding)stringEncoding {
|
|
|
- return [NSString stringWithFormat:@"%@=%@", self.key, AFURLEncodedStringFromStringWithEncoding([self.value description], stringEncoding)];
|
|
|
+ return [NSString stringWithFormat:@"%@=%@", AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(self.field, stringEncoding), AFPercentEscapedQueryStringPairMemberFromStringWithEncoding([self.value description], stringEncoding)];
|
|
|
}
|
|
|
|
|
|
@end
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
-extern NSArray * AFQueryStringComponentsFromKeyAndValue(NSString *key, id value);
|
|
|
-extern NSArray * AFQueryStringComponentsFromKeyAndDictionaryValue(NSString *key, NSDictionary *value);
|
|
|
-extern NSArray * AFQueryStringComponentsFromKeyAndArrayValue(NSString *key, NSArray *value);
|
|
|
+extern NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary);
|
|
|
+extern NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value);
|
|
|
|
|
|
NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *parameters, NSStringEncoding stringEncoding) {
|
|
|
- NSMutableArray *mutableComponents = [NSMutableArray array];
|
|
|
- for (AFQueryStringComponent *component in AFQueryStringComponentsFromKeyAndValue(nil, parameters)) {
|
|
|
- [mutableComponents addObject:[component URLEncodedStringValueWithEncoding:stringEncoding]];
|
|
|
+ NSMutableArray *mutablePairs = [NSMutableArray array];
|
|
|
+ for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
|
|
|
+ [mutablePairs addObject:[pair URLEncodedStringValueWithEncoding:stringEncoding]];
|
|
|
}
|
|
|
|
|
|
- return [mutableComponents componentsJoinedByString:@"&"];
|
|
|
+ return [mutablePairs componentsJoinedByString:@"&"];
|
|
|
}
|
|
|
|
|
|
-NSArray * AFQueryStringComponentsFromKeyAndValue(NSString *key, id value) {
|
|
|
+NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary) {
|
|
|
+ return AFQueryStringPairsFromKeyAndValue(nil, dictionary);
|
|
|
+}
|
|
|
+
|
|
|
+NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
|
|
|
NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
|
|
|
|
|
if([value isKindOfClass:[NSDictionary class]]) {
|
|
|
- [mutableQueryStringComponents addObjectsFromArray:AFQueryStringComponentsFromKeyAndDictionaryValue(key, value)];
|
|
|
+ [value enumerateKeysAndObjectsUsingBlock:^(id nestedKey, id nestedValue, BOOL *stop) {
|
|
|
+ [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
|
|
|
+ }];
|
|
|
} else if([value isKindOfClass:[NSArray class]]) {
|
|
|
- [mutableQueryStringComponents addObjectsFromArray:AFQueryStringComponentsFromKeyAndArrayValue(key, value)];
|
|
|
+ [value enumerateObjectsUsingBlock:^(id nestedValue, NSUInteger idx, BOOL *stop) {
|
|
|
+ [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
|
|
|
+ }];
|
|
|
} else {
|
|
|
- [mutableQueryStringComponents addObject:[[AFQueryStringComponent alloc] initWithKey:key value:value]];
|
|
|
- }
|
|
|
-
|
|
|
- return mutableQueryStringComponents;
|
|
|
-}
|
|
|
-
|
|
|
-NSArray * AFQueryStringComponentsFromKeyAndDictionaryValue(NSString *key, NSDictionary *value){
|
|
|
- NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
|
|
-
|
|
|
- [value enumerateKeysAndObjectsUsingBlock:^(id nestedKey, id nestedValue, BOOL *stop) {
|
|
|
- [mutableQueryStringComponents addObjectsFromArray:AFQueryStringComponentsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
|
|
|
- }];
|
|
|
-
|
|
|
- return mutableQueryStringComponents;
|
|
|
-}
|
|
|
-
|
|
|
-NSArray * AFQueryStringComponentsFromKeyAndArrayValue(NSString *key, NSArray *value) {
|
|
|
- NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
|
|
-
|
|
|
- [value enumerateObjectsUsingBlock:^(id nestedValue, NSUInteger idx, BOOL *stop) {
|
|
|
- [mutableQueryStringComponents addObjectsFromArray:AFQueryStringComponentsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
|
|
|
- }];
|
|
|
+ [mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
|
|
|
+ }
|
|
|
|
|
|
return mutableQueryStringComponents;
|
|
|
}
|
|
@@ -245,6 +231,11 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
|
|
|
return nil;
|
|
|
}
|
|
|
|
|
|
+ // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected
|
|
|
+ if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
|
|
|
+ url = [url URLByAppendingPathComponent:@""];
|
|
|
+ }
|
|
|
+
|
|
|
self.baseURL = url;
|
|
|
|
|
|
self.stringEncoding = NSUTF8StringEncoding;
|
|
@@ -253,19 +244,16 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
|
|
|
self.registeredHTTPOperationClassNames = [NSMutableArray array];
|
|
|
|
|
|
self.defaultHeaders = [NSMutableDictionary dictionary];
|
|
|
-
|
|
|
- // Accept-Encoding HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
|
|
|
- [self setDefaultHeader:@"Accept-Encoding" value:@"gzip"];
|
|
|
|
|
|
- // Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
|
|
|
- NSString *preferredLanguageCodes = [[NSLocale preferredLanguages] componentsJoinedByString:@", "];
|
|
|
- [self setDefaultHeader:@"Accept-Language" value:[NSString stringWithFormat:@"%@, en-us;q=0.8", preferredLanguageCodes]];
|
|
|
+ // Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
|
|
|
+ NSString *preferredLanguageCodes = [[NSLocale preferredLanguages] componentsJoinedByString:@", "];
|
|
|
+ [self setDefaultHeader:@"Accept-Language" value:[NSString stringWithFormat:@"%@, en-us;q=0.8", preferredLanguageCodes]];
|
|
|
|
|
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
|
|
// 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 setDefaultHeader:@"User-Agent" value:[NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleIdentifierKey], (__bridge id)CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), kCFBundleVersionKey) ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] ? [[UIScreen mainScreen] scale] : 1.0f)]];
|
|
|
#elif __MAC_OS_X_VERSION_MIN_REQUIRED
|
|
|
- [self setDefaultHeader:@"User-Agent" value:[NSString stringWithFormat:@"%@/%@ (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey], @"unknown"]];
|
|
|
+ [self setDefaultHeader:@"User-Agent" value:[NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]]];
|
|
|
#endif
|
|
|
|
|
|
#ifdef _SYSTEMCONFIGURATION_H
|
|
@@ -274,7 +262,7 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
|
|
|
#endif
|
|
|
|
|
|
self.operationQueue = [[NSOperationQueue alloc] init];
|
|
|
- [self.operationQueue setMaxConcurrentOperationCount:kAFHTTPClientDefaultMaxConcurrentOperationCount];
|
|
|
+ [self.operationQueue setMaxConcurrentOperationCount:NSOperationQueueDefaultMaxConcurrentOperationCount];
|
|
|
|
|
|
return self;
|
|
|
}
|
|
@@ -320,14 +308,14 @@ static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetwork
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
-static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
|
|
|
+static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
|
|
|
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
|
|
|
AFNetworkReachabilityStatusBlock block = (__bridge AFNetworkReachabilityStatusBlock)info;
|
|
|
if (block) {
|
|
|
block(status);
|
|
|
}
|
|
|
|
|
|
- [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingReachabilityDidChangeNotification object:[NSNumber numberWithInt:status]];
|
|
|
+ [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:status] forKey:AFNetworkingReachabilityNotificationStatusItem]];
|
|
|
}
|
|
|
|
|
|
static const void * AFNetworkReachabilityRetainCallback(const void *info) {
|
|
@@ -425,10 +413,10 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
-- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
|
|
|
- path:(NSString *)path
|
|
|
- parameters:(NSDictionary *)parameters
|
|
|
-{
|
|
|
+- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
|
|
|
+ path:(NSString *)path
|
|
|
+ parameters:(NSDictionary *)parameters
|
|
|
+{
|
|
|
NSURL *url = [NSURL URLWithString:path relativeToURL:self.baseURL];
|
|
|
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
|
|
|
[request setHTTPMethod:method];
|
|
@@ -439,7 +427,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
[request setHTTPShouldUsePipelining:YES];
|
|
|
}
|
|
|
|
|
|
- if (parameters) {
|
|
|
+ if (parameters) {
|
|
|
if ([method isEqualToString:@"GET"] || [method isEqualToString:@"HEAD"] || [method isEqualToString:@"DELETE"]) {
|
|
|
url = [NSURL URLWithString:[[url absoluteString] stringByAppendingFormat:[path rangeOfString:@"?"].location == NSNotFound ? @"?%@" : @"&%@", AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding)]];
|
|
|
[request setURL:url];
|
|
@@ -474,16 +462,16 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
__block AFMultipartFormData *formData = [[AFMultipartFormData alloc] initWithURLRequest:request stringEncoding:self.stringEncoding];
|
|
|
|
|
|
if (parameters) {
|
|
|
- for (AFQueryStringComponent *component in AFQueryStringComponentsFromKeyAndValue(nil, parameters)) {
|
|
|
+ for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
|
|
|
NSData *data = nil;
|
|
|
- if ([component.value isKindOfClass:[NSData class]]) {
|
|
|
- data = component.value;
|
|
|
+ if ([pair.value isKindOfClass:[NSData class]]) {
|
|
|
+ data = pair.value;
|
|
|
} else {
|
|
|
- data = [[component.value description] dataUsingEncoding:self.stringEncoding];
|
|
|
+ data = [[pair.value description] dataUsingEncoding:self.stringEncoding];
|
|
|
}
|
|
|
|
|
|
if (data) {
|
|
|
- [formData appendPartWithFormData:data name:[component.key description]];
|
|
|
+ [formData appendPartWithFormData:data name:[pair.field description]];
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -495,7 +483,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
return [formData requestByFinalizingMultipartFormData];
|
|
|
}
|
|
|
|
|
|
-- (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
|
|
+- (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
|
|
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
|
|
|
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
|
|
|
{
|
|
@@ -536,8 +524,8 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-- (void)enqueueBatchOfHTTPRequestOperationsWithRequests:(NSArray *)requests
|
|
|
- progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock
|
|
|
+- (void)enqueueBatchOfHTTPRequestOperationsWithRequests:(NSArray *)requests
|
|
|
+ progressBlock:(void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations))progressBlock
|
|
|
completionBlock:(void (^)(NSArray *operations))completionBlock
|
|
|
{
|
|
|
NSMutableArray *mutableOperations = [NSMutableArray array];
|
|
@@ -549,8 +537,8 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
[self enqueueBatchOfHTTPRequestOperations:mutableOperations progressBlock:progressBlock completionBlock:completionBlock];
|
|
|
}
|
|
|
|
|
|
-- (void)enqueueBatchOfHTTPRequestOperations:(NSArray *)operations
|
|
|
- progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock
|
|
|
+- (void)enqueueBatchOfHTTPRequestOperations:(NSArray *)operations
|
|
|
+ progressBlock:(void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations))progressBlock
|
|
|
completionBlock:(void (^)(NSArray *operations))completionBlock
|
|
|
{
|
|
|
__block dispatch_group_t dispatchGroup = dispatch_group_create();
|
|
@@ -563,8 +551,6 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
dispatch_release(dispatchGroup);
|
|
|
}];
|
|
|
|
|
|
- NSPredicate *finishedOperationPredicate = [NSPredicate predicateWithFormat:@"isFinished == YES"];
|
|
|
-
|
|
|
for (AFHTTPRequestOperation *operation in operations) {
|
|
|
AFCompletionBlock originalCompletionBlock = [operation.completionBlock copy];
|
|
|
operation.completionBlock = ^{
|
|
@@ -574,8 +560,15 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
originalCompletionBlock();
|
|
|
}
|
|
|
|
|
|
+ __block NSUInteger numberOfFinishedOperations = 0;
|
|
|
+ [operations enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
|
|
+ if ([(NSOperation *)obj isFinished]) {
|
|
|
+ numberOfFinishedOperations++;
|
|
|
+ }
|
|
|
+ }];
|
|
|
+
|
|
|
if (progressBlock) {
|
|
|
- progressBlock([[operations filteredArrayUsingPredicate:finishedOperationPredicate] count], [operations count]);
|
|
|
+ progressBlock(numberOfFinishedOperations, [operations count]);
|
|
|
}
|
|
|
|
|
|
dispatch_group_leave(dispatchGroup);
|
|
@@ -592,8 +585,8 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
|
-- (void)getPath:(NSString *)path
|
|
|
- parameters:(NSDictionary *)parameters
|
|
|
+- (void)getPath:(NSString *)path
|
|
|
+ parameters:(NSDictionary *)parameters
|
|
|
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
|
|
|
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
|
|
|
{
|
|
@@ -602,8 +595,8 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
[self enqueueHTTPRequestOperation:operation];
|
|
|
}
|
|
|
|
|
|
-- (void)postPath:(NSString *)path
|
|
|
- parameters:(NSDictionary *)parameters
|
|
|
+- (void)postPath:(NSString *)path
|
|
|
+ parameters:(NSDictionary *)parameters
|
|
|
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
|
|
|
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
|
|
|
{
|
|
@@ -612,8 +605,8 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
[self enqueueHTTPRequestOperation:operation];
|
|
|
}
|
|
|
|
|
|
-- (void)putPath:(NSString *)path
|
|
|
- parameters:(NSDictionary *)parameters
|
|
|
+- (void)putPath:(NSString *)path
|
|
|
+ parameters:(NSDictionary *)parameters
|
|
|
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
|
|
|
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
|
|
|
{
|
|
@@ -622,8 +615,8 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
[self enqueueHTTPRequestOperation:operation];
|
|
|
}
|
|
|
|
|
|
-- (void)deletePath:(NSString *)path
|
|
|
- parameters:(NSDictionary *)parameters
|
|
|
+- (void)deletePath:(NSString *)path
|
|
|
+ parameters:(NSDictionary *)parameters
|
|
|
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
|
|
|
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
|
|
|
{
|
|
@@ -632,8 +625,8 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
[self enqueueHTTPRequestOperation:operation];
|
|
|
}
|
|
|
|
|
|
-- (void)patchPath:(NSString *)path
|
|
|
- parameters:(NSDictionary *)parameters
|
|
|
+- (void)patchPath:(NSString *)path
|
|
|
+ parameters:(NSDictionary *)parameters
|
|
|
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
|
|
|
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
|
|
|
{
|
|
@@ -642,6 +635,47 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
|
|
[self enqueueHTTPRequestOperation:operation];
|
|
|
}
|
|
|
|
|
|
+#pragma mark - NSCoding
|
|
|
+
|
|
|
+- (id)initWithCoder:(NSCoder *)aDecoder {
|
|
|
+ NSURL *baseURL = [aDecoder decodeObjectForKey:@"baseURL"];
|
|
|
+
|
|
|
+ self = [self initWithBaseURL:baseURL];
|
|
|
+ if (!self) {
|
|
|
+ return nil;
|
|
|
+ }
|
|
|
+
|
|
|
+ self.stringEncoding = [aDecoder decodeIntegerForKey:@"stringEncoding"];
|
|
|
+ self.parameterEncoding = [aDecoder decodeIntegerForKey:@"parameterEncoding"];
|
|
|
+ self.registeredHTTPOperationClassNames = [aDecoder decodeObjectForKey:@"registeredHTTPOperationClassNames"];
|
|
|
+ self.defaultHeaders = [aDecoder decodeObjectForKey:@"defaultHeaders"];
|
|
|
+
|
|
|
+ return self;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)encodeWithCoder:(NSCoder *)aCoder {
|
|
|
+ [aCoder encodeObject:self.baseURL forKey:@"baseURL"];
|
|
|
+ [aCoder encodeInteger:self.stringEncoding forKey:@"stringEncoding"];
|
|
|
+ [aCoder encodeInteger:self.parameterEncoding forKey:@"parameterEncoding"];
|
|
|
+ [aCoder encodeObject:self.registeredHTTPOperationClassNames forKey:@"registeredHTTPOperationClassNames"];
|
|
|
+ [aCoder encodeObject:self.defaultHeaders forKey:@"defaultHeaders"];
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - NSCopying
|
|
|
+
|
|
|
+- (id)copyWithZone:(NSZone *)zone {
|
|
|
+ AFHTTPClient *HTTPClient = [[[self class] allocWithZone:zone] initWithBaseURL:self.baseURL];
|
|
|
+
|
|
|
+ HTTPClient.stringEncoding = self.stringEncoding;
|
|
|
+ HTTPClient.parameterEncoding = self.parameterEncoding;
|
|
|
+ HTTPClient.registeredHTTPOperationClassNames = [self.registeredHTTPOperationClassNames copyWithZone:zone];
|
|
|
+ HTTPClient.defaultHeaders = [self.defaultHeaders copyWithZone:zone];
|
|
|
+#ifdef _SYSTEMCONFIGURATION_H
|
|
|
+ HTTPClient.networkReachabilityStatusBlock = self.networkReachabilityStatusBlock;
|
|
|
+#endif
|
|
|
+ return HTTPClient;
|
|
|
+}
|
|
|
+
|
|
|
@end
|
|
|
|
|
|
#pragma mark -
|
|
@@ -656,7 +690,7 @@ static NSString * AFMultipartTemporaryFileDirectoryPath() {
|
|
|
|
|
|
NSError *error = nil;
|
|
|
if(![[NSFileManager defaultManager] createDirectoryAtPath:multipartTemporaryFilePath withIntermediateDirectories:YES attributes:nil error:&error]) {
|
|
|
- NSLog(@"Failed to create multipary temporary file directory at %@", multipartTemporaryFilePath);
|
|
|
+ NSLog(@"Failed to create multipart temporary file directory at %@", multipartTemporaryFilePath);
|
|
|
}
|
|
|
});
|
|
|
|
|
@@ -682,8 +716,8 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
|
|
@interface AFMultipartFormData ()
|
|
|
@property (readwrite, nonatomic) NSMutableURLRequest *request;
|
|
|
@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
|
|
|
-@property (readwrite, nonatomic) NSOutputStream *outputStream;
|
|
|
-@property (readwrite, nonatomic, copy) NSString *temporaryFilePath;
|
|
|
+@property (readwrite, nonatomic, strong) NSOutputStream *outputStream;
|
|
|
+@property (readwrite, nonatomic, copy) NSString *temporaryFilePath;
|
|
|
@end
|
|
|
|
|
|
@implementation AFMultipartFormData
|
|
@@ -692,8 +726,8 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
|
|
@synthesize outputStream = _outputStream;
|
|
|
@synthesize temporaryFilePath = _temporaryFilePath;
|
|
|
|
|
|
-- (id)initWithURLRequest:(NSMutableURLRequest *)request
|
|
|
- stringEncoding:(NSStringEncoding)encoding
|
|
|
+- (id)initWithURLRequest:(NSMutableURLRequest *)request
|
|
|
+ stringEncoding:(NSStringEncoding)encoding
|
|
|
{
|
|
|
self = [super init];
|
|
|
if (!self) {
|
|
@@ -703,7 +737,7 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
|
|
self.request = request;
|
|
|
self.stringEncoding = encoding;
|
|
|
|
|
|
- self.temporaryFilePath = [AFMultipartTemporaryFileDirectoryPath() stringByAppendingPathComponent:[NSString stringWithFormat:@"%u", [[self.request URL] hash]]];
|
|
|
+ self.temporaryFilePath = [AFMultipartTemporaryFileDirectoryPath() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
|
|
|
self.outputStream = [NSOutputStream outputStreamToFileAtPath:self.temporaryFilePath append:NO];
|
|
|
|
|
|
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
|
@@ -728,7 +762,7 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
|
|
|
|
|
return self.request;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
[self appendData:[AFMultipartFormFinalBoundary() dataUsingEncoding:self.stringEncoding]];
|
|
|
|
|
|
[self.request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", kAFMultipartFormBoundary] forHTTPHeaderField:@"Content-Type"];
|
|
@@ -750,8 +784,8 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-- (void)appendPartWithHeaders:(NSDictionary *)headers
|
|
|
- body:(NSData *)body
|
|
|
+- (void)appendPartWithHeaders:(NSDictionary *)headers
|
|
|
+ body:(NSData *)body
|
|
|
{
|
|
|
[self appendBoundary];
|
|
|
|
|
@@ -763,8 +797,8 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
|
|
[self appendData:body];
|
|
|
}
|
|
|
|
|
|
-- (void)appendPartWithFormData:(NSData *)data
|
|
|
- name:(NSString *)name
|
|
|
+- (void)appendPartWithFormData:(NSData *)data
|
|
|
+ name:(NSString *)name
|
|
|
{
|
|
|
NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
|
|
|
[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"", name] forKey:@"Content-Disposition"];
|
|
@@ -772,11 +806,11 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
|
|
[self appendPartWithHeaders:mutableHeaders body:data];
|
|
|
}
|
|
|
|
|
|
-- (void)appendPartWithFileData:(NSData *)data
|
|
|
- name:(NSString *)name
|
|
|
- fileName:(NSString *)fileName
|
|
|
+- (void)appendPartWithFileData:(NSData *)data
|
|
|
+ name:(NSString *)name
|
|
|
+ fileName:(NSString *)fileName
|
|
|
mimeType:(NSString *)mimeType
|
|
|
-{
|
|
|
+{
|
|
|
NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
|
|
|
[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
|
|
|
[mutableHeaders setValue:mimeType forKey:@"Content-Type"];
|
|
@@ -784,16 +818,16 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
|
|
[self appendPartWithHeaders:mutableHeaders body:data];
|
|
|
}
|
|
|
|
|
|
-- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
|
|
|
- name:(NSString *)name
|
|
|
- error:(NSError **)error
|
|
|
+- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
|
|
|
+ name:(NSString *)name
|
|
|
+ error:(NSError **)error
|
|
|
{
|
|
|
if (![fileURL isFileURL]) {
|
|
|
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
|
|
|
[userInfo setValue:fileURL forKey:NSURLErrorFailingURLErrorKey];
|
|
|
[userInfo setValue:NSLocalizedString(@"Expected URL to be a file URL", nil) forKey:NSLocalizedFailureReasonErrorKey];
|
|
|
if (error != NULL) {
|
|
|
- *error = [[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadURL userInfo:userInfo];
|
|
|
+ *error = [[NSError alloc] initWithDomain:NSURLErrorDomain code:NSURLErrorBadURL userInfo:userInfo];
|
|
|
}
|
|
|
|
|
|
return NO;
|
|
@@ -822,7 +856,7 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
|
|
if ([data length] == 0) {
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if ([self.outputStream hasSpaceAvailable]) {
|
|
|
const uint8_t *dataBuffer = (uint8_t *) [data bytes];
|
|
|
[self.outputStream write:&dataBuffer[0] maxLength:[data length]];
|