Merge branch 'master' into invalid-ssl
This commit is contained in:
commit
bcb8aea682
17 changed files with 719 additions and 329 deletions
|
|
@ -1,22 +1,25 @@
|
||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = 'AFNetworking'
|
s.name = 'AFNetworking'
|
||||||
s.version = '1.1.0'
|
s.version = '1.2.0'
|
||||||
s.license = 'MIT'
|
s.license = 'MIT'
|
||||||
s.summary = 'A delightful iOS and OS X networking framework.'
|
s.summary = 'A delightful iOS and OS X networking framework.'
|
||||||
s.homepage = 'https://github.com/AFNetworking/AFNetworking'
|
s.homepage = 'https://github.com/AFNetworking/AFNetworking'
|
||||||
s.authors = { 'Mattt Thompson' => 'm@mattt.me', 'Scott Raymond' => 'sco@gowalla.com' }
|
s.authors = { 'Mattt Thompson' => 'm@mattt.me', 'Scott Raymond' => 'sco@gowalla.com' }
|
||||||
s.source = { :git => 'https://github.com/AFNetworking/AFNetworking.git', :tag => '1.1.0' }
|
s.source = { :git => 'https://github.com/AFNetworking/AFNetworking.git', :tag => '1.2.0' }
|
||||||
s.source_files = 'AFNetworking'
|
s.source_files = 'AFNetworking'
|
||||||
s.requires_arc = true
|
s.requires_arc = true
|
||||||
|
|
||||||
s.ios.deployment_target = '5.0'
|
s.ios.deployment_target = '5.0'
|
||||||
s.ios.frameworks = 'MobileCoreServices', 'SystemConfiguration'
|
s.ios.frameworks = 'MobileCoreServices', 'SystemConfiguration', 'Security'
|
||||||
|
|
||||||
s.osx.deployment_target = '10.7'
|
s.osx.deployment_target = '10.7'
|
||||||
s.osx.frameworks = 'CoreServices', 'SystemConfiguration'
|
s.osx.frameworks = 'CoreServices', 'SystemConfiguration', 'Security'
|
||||||
|
|
||||||
s.prefix_header_contents = <<-EOS
|
s.prefix_header_contents = <<-EOS
|
||||||
#import <Availability.h>
|
#import <Availability.h>
|
||||||
|
|
||||||
|
#define _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
|
||||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
#import <SystemConfiguration/SystemConfiguration.h>
|
#import <SystemConfiguration/SystemConfiguration.h>
|
||||||
#import <MobileCoreServices/MobileCoreServices.h>
|
#import <MobileCoreServices/MobileCoreServices.h>
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "AFURLConnectionOperation.h"
|
||||||
|
|
||||||
#import <Availability.h>
|
#import <Availability.h>
|
||||||
|
|
||||||
|
|
@ -137,6 +138,13 @@ typedef enum {
|
||||||
@property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
|
@property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Default SSL pinning mode for each `AFHTTPRequestOperation` which will be enqueued with `enqueueHTTPRequestOperation:`.
|
||||||
|
*/
|
||||||
|
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
@property (nonatomic, assign) AFURLConnectionOperationSSLPinningMode defaultSSLPinningMode;
|
||||||
|
#endif
|
||||||
|
|
||||||
///---------------------------------------------
|
///---------------------------------------------
|
||||||
/// @name Creating and Initializing HTTP Clients
|
/// @name Creating and Initializing HTTP Clients
|
||||||
///---------------------------------------------
|
///---------------------------------------------
|
||||||
|
|
@ -440,7 +448,7 @@ typedef enum {
|
||||||
///----------------
|
///----------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
### Network Reachability
|
## Network Reachability
|
||||||
|
|
||||||
The following constants are provided by `AFHTTPClient` as possible network reachability statuses.
|
The following constants are provided by `AFHTTPClient` as possible network reachability statuses.
|
||||||
|
|
||||||
|
|
@ -471,7 +479,7 @@ typedef enum {
|
||||||
A key in the userInfo dictionary in a `AFNetworkingReachabilityDidChangeNotification` notification.
|
A key in the userInfo dictionary in a `AFNetworkingReachabilityDidChangeNotification` notification.
|
||||||
The corresponding value is an `NSNumber` object representing the `AFNetworkReachabilityStatus` value for the current reachability status.
|
The corresponding value is an `NSNumber` object representing the `AFNetworkReachabilityStatus` value for the current reachability status.
|
||||||
|
|
||||||
### Parameter Encoding
|
## Parameter Encoding
|
||||||
|
|
||||||
The following constants are provided by `AFHTTPClient` as possible methods for serializing parameters into query string or message body values.
|
The following constants are provided by `AFHTTPClient` as possible methods for serializing parameters into query string or message body values.
|
||||||
|
|
||||||
|
|
@ -543,12 +551,44 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay;
|
||||||
|
|
||||||
@return `YES` if the file data was successfully appended, otherwise `NO`.
|
@return `YES` if the file data was successfully appended, otherwise `NO`.
|
||||||
|
|
||||||
@discussion The filename and MIME type for this data in the form will be automatically generated, using `NSURLResponse` `-suggestedFilename` and `-MIMEType`, respectively.
|
@discussion The filename and MIME type for this data in the form will be automatically generated, using the last path component of the `fileURL` and system associated MIME type for the `fileURL` extension, respectively.
|
||||||
*/
|
*/
|
||||||
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
|
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
|
||||||
name:(NSString *)name
|
name:(NSString *)name
|
||||||
error:(NSError * __autoreleasing *)error;
|
error:(NSError * __autoreleasing *)error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary.
|
||||||
|
|
||||||
|
@param fileURL The URL corresponding to the file whose content will be appended to the form. This parameter must not be `nil`.
|
||||||
|
@param name The name to be associated with the specified data. This parameter must not be `nil`.
|
||||||
|
@param fileName The file name to be used in the `Content-Disposition` header. This parameter must not be `nil`.
|
||||||
|
@param mimeType The declared MIME type of the file data. This parameter must not be `nil`.
|
||||||
|
@param error If an error occurs, upon return contains an `NSError` object that describes the problem.
|
||||||
|
|
||||||
|
@return `YES` if the file data was successfully appended otherwise `NO`.
|
||||||
|
*/
|
||||||
|
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
|
||||||
|
name:(NSString *)name
|
||||||
|
fileName:(NSString *)fileName
|
||||||
|
mimeType:(NSString *)mimeType
|
||||||
|
error:(NSError * __autoreleasing *)error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the data from the input stream and the multipart form boundary.
|
||||||
|
|
||||||
|
@param inputStream The input stream to be appended to the form data
|
||||||
|
@param name The name to be associated with the specified input stream. This parameter must not be `nil`.
|
||||||
|
@param fileName The filename to be associated with the specified input stream. This parameter must not be `nil`.
|
||||||
|
@param length The length of the specified input stream in bytes.
|
||||||
|
@param mimeType The MIME type of the specified data. (For example, the MIME type for a JPEG image is image/jpeg.) For a list of valid MIME types, see http://www.iana.org/assignments/media-types/. This parameter must not be `nil`.
|
||||||
|
*/
|
||||||
|
- (void)appendPartWithInputStream:(NSInputStream *)inputStream
|
||||||
|
name:(NSString *)name
|
||||||
|
fileName:(NSString *)fileName
|
||||||
|
length:(unsigned long long)length
|
||||||
|
mimeType:(NSString *)mimeType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary.
|
Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary.
|
||||||
|
|
||||||
|
|
@ -572,6 +612,7 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay;
|
||||||
- (void)appendPartWithFormData:(NSData *)data
|
- (void)appendPartWithFormData:(NSData *)data
|
||||||
name:(NSString *)name;
|
name:(NSString *)name;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Appends HTTP headers, followed by the encoded data and the multipart form boundary.
|
Appends HTTP headers, followed by the encoded data and the multipart form boundary.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ static NSString * AFBase64EncodedStringFromString(NSString *string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
|
static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
|
||||||
static NSString * const kAFCharactersToBeEscaped = @":/?&=;+!@#$()~'";
|
static NSString * const kAFCharactersToBeEscaped = @":/?&=;+!@#$()~',*";
|
||||||
static NSString * const kAFCharactersToLeaveUnescaped = @"[].";
|
static NSString * const kAFCharactersToLeaveUnescaped = @"[].";
|
||||||
|
|
||||||
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFCharactersToLeaveUnescaped, (__bridge CFStringRef)kAFCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding));
|
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFCharactersToLeaveUnescaped, (__bridge CFStringRef)kAFCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding));
|
||||||
|
|
@ -146,10 +146,11 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
|
||||||
NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
|
||||||
|
|
||||||
if ([value isKindOfClass:[NSDictionary class]]) {
|
if ([value isKindOfClass:[NSDictionary class]]) {
|
||||||
|
NSDictionary *dictionary = value;
|
||||||
// Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries
|
// Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries
|
||||||
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(caseInsensitiveCompare:)];
|
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(caseInsensitiveCompare:)];
|
||||||
[[[value allKeys] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]] enumerateObjectsUsingBlock:^(id nestedKey, __unused NSUInteger idx, __unused BOOL *stop) {
|
[[[dictionary allKeys] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]] enumerateObjectsUsingBlock:^(id nestedKey, __unused NSUInteger idx, __unused BOOL *stop) {
|
||||||
id nestedValue = [value objectForKey:nestedKey];
|
id nestedValue = [dictionary objectForKey:nestedKey];
|
||||||
if (nestedValue) {
|
if (nestedValue) {
|
||||||
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
|
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
|
||||||
}
|
}
|
||||||
|
|
@ -159,6 +160,11 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
|
||||||
[array enumerateObjectsUsingBlock:^(id nestedValue, __unused NSUInteger idx, __unused BOOL *stop) {
|
[array enumerateObjectsUsingBlock:^(id nestedValue, __unused NSUInteger idx, __unused BOOL *stop) {
|
||||||
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
|
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
|
||||||
}];
|
}];
|
||||||
|
} else if ([value isKindOfClass:[NSSet class]]) {
|
||||||
|
NSSet *set = value;
|
||||||
|
[set enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
|
||||||
|
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue(key, obj)];
|
||||||
|
}];
|
||||||
} else {
|
} else {
|
||||||
[mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
|
[mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
|
||||||
}
|
}
|
||||||
|
|
@ -234,9 +240,14 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
|
||||||
self.defaultHeaders = [NSMutableDictionary dictionary];
|
self.defaultHeaders = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
// Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
|
// Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
|
||||||
NSString *preferredLanguageCodes = [[NSLocale preferredLanguages] componentsJoinedByString:@", "];
|
NSMutableArray *acceptLanguagesComponents = [NSMutableArray array];
|
||||||
[self setDefaultHeader:@"Accept-Language" value:[NSString stringWithFormat:@"%@, en-us;q=0.8", preferredLanguageCodes]];
|
[[NSLocale preferredLanguages] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||||
|
float q = 1.0f - (idx * 0.1f);
|
||||||
|
[acceptLanguagesComponents addObject:[NSString stringWithFormat:@"%@;q=%0.1g", obj, q]];
|
||||||
|
*stop = q <= 0.5f;
|
||||||
|
}];
|
||||||
|
[self setDefaultHeader:@"Accept-Language" value:[acceptLanguagesComponents componentsJoinedByString:@", "]];
|
||||||
|
|
||||||
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
|
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
|
||||||
// User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
|
// User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
|
||||||
[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)]];
|
[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)]];
|
||||||
|
|
@ -304,7 +315,8 @@ static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused targ
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:status] forKey:AFNetworkingReachabilityNotificationStatusItem]];
|
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||||
|
[notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:status] forKey:AFNetworkingReachabilityNotificationStatusItem]];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -505,12 +517,12 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
||||||
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
|
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
|
||||||
{
|
{
|
||||||
AFHTTPRequestOperation *operation = nil;
|
AFHTTPRequestOperation *operation = nil;
|
||||||
NSString *className = nil;
|
|
||||||
NSEnumerator *enumerator = [self.registeredHTTPOperationClassNames reverseObjectEnumerator];
|
for (NSString *className in self.registeredHTTPOperationClassNames) {
|
||||||
while (!operation && (className = [enumerator nextObject])) {
|
Class operationClass = NSClassFromString(className);
|
||||||
Class op_class = NSClassFromString(className);
|
if (operationClass && [operationClass canProcessRequest:urlRequest]) {
|
||||||
if (op_class && [op_class canProcessRequest:urlRequest]) {
|
operation = [(AFHTTPRequestOperation *)[operationClass alloc] initWithRequest:urlRequest];
|
||||||
operation = [(AFHTTPRequestOperation *)[op_class alloc] initWithRequest:urlRequest];
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -521,6 +533,9 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
||||||
[operation setCompletionBlockWithSuccess:success failure:failure];
|
[operation setCompletionBlockWithSuccess:success failure:failure];
|
||||||
|
|
||||||
operation.credential = self.defaultCredential;
|
operation.credential = self.defaultCredential;
|
||||||
|
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
operation.SSLPinningMode = self.defaultSSLPinningMode;
|
||||||
|
#endif
|
||||||
|
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
|
|
@ -534,7 +549,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
||||||
- (void)cancelAllHTTPOperationsWithMethod:(NSString *)method
|
- (void)cancelAllHTTPOperationsWithMethod:(NSString *)method
|
||||||
path:(NSString *)path
|
path:(NSString *)path
|
||||||
{
|
{
|
||||||
NSString *URLStringToMatched = [[[self requestWithMethod:(method ?: @"GET") path:path parameters:nil] URL] absoluteString];
|
NSString *pathToBeMatched = [[[self requestWithMethod:(method ?: @"GET") path:path parameters:nil] URL] path];
|
||||||
|
|
||||||
for (NSOperation *operation in [self.operationQueue operations]) {
|
for (NSOperation *operation in [self.operationQueue operations]) {
|
||||||
if (![operation isKindOfClass:[AFHTTPRequestOperation class]]) {
|
if (![operation isKindOfClass:[AFHTTPRequestOperation class]]) {
|
||||||
|
|
@ -542,9 +557,9 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL hasMatchingMethod = !method || [method isEqualToString:[[(AFHTTPRequestOperation *)operation request] HTTPMethod]];
|
BOOL hasMatchingMethod = !method || [method isEqualToString:[[(AFHTTPRequestOperation *)operation request] HTTPMethod]];
|
||||||
BOOL hasMatchingURL = [[[[(AFHTTPRequestOperation *)operation request] URL] absoluteString] isEqualToString:URLStringToMatched];
|
BOOL hasMatchingPath = [[[[(AFHTTPRequestOperation *)operation request] URL] path] isEqual:pathToBeMatched];
|
||||||
|
|
||||||
if (hasMatchingMethod && hasMatchingURL) {
|
if (hasMatchingMethod && hasMatchingPath) {
|
||||||
[operation cancel];
|
[operation cancel];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -581,9 +596,10 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
||||||
|
|
||||||
for (AFHTTPRequestOperation *operation in operations) {
|
for (AFHTTPRequestOperation *operation in operations) {
|
||||||
AFCompletionBlock originalCompletionBlock = [operation.completionBlock copy];
|
AFCompletionBlock originalCompletionBlock = [operation.completionBlock copy];
|
||||||
__weak AFHTTPRequestOperation *weakOperation = operation;
|
__weak __typeof(&*operation)weakOperation = operation;
|
||||||
operation.completionBlock = ^{
|
operation.completionBlock = ^{
|
||||||
dispatch_queue_t queue = weakOperation.successCallbackQueue ?: dispatch_get_main_queue();
|
__strong __typeof(&*weakOperation)strongOperation = weakOperation;
|
||||||
|
dispatch_queue_t queue = strongOperation.successCallbackQueue ?: dispatch_get_main_queue();
|
||||||
dispatch_group_async(dispatchGroup, queue, ^{
|
dispatch_group_async(dispatchGroup, queue, ^{
|
||||||
if (originalCompletionBlock) {
|
if (originalCompletionBlock) {
|
||||||
originalCompletionBlock();
|
originalCompletionBlock();
|
||||||
|
|
@ -729,7 +745,12 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
||||||
static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
||||||
#ifdef __UTTYPE__
|
#ifdef __UTTYPE__
|
||||||
NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL);
|
NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL);
|
||||||
return (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)UTI, kUTTagClassMIMEType);
|
NSString *contentType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)UTI, kUTTagClassMIMEType);
|
||||||
|
if (!contentType) {
|
||||||
|
return @"application/octet-stream";
|
||||||
|
} else {
|
||||||
|
return contentType;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return @"application/octet-stream";
|
return @"application/octet-stream";
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -755,9 +776,10 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
maxLength:(NSUInteger)length;
|
maxLength:(NSUInteger)length;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface AFMultipartBodyStream : NSInputStream <NSStreamDelegate>
|
@interface AFMultipartBodyStreamProvider : NSObject
|
||||||
@property (nonatomic, assign) NSUInteger numberOfBytesInPacket;
|
@property (nonatomic, assign) NSUInteger bufferLength;
|
||||||
@property (nonatomic, assign) NSTimeInterval delay;
|
@property (nonatomic, assign) NSTimeInterval delay;
|
||||||
|
@property (nonatomic, readonly) NSInputStream *inputStream;
|
||||||
@property (nonatomic, readonly) unsigned long long contentLength;
|
@property (nonatomic, readonly) unsigned long long contentLength;
|
||||||
@property (nonatomic, readonly, getter = isEmpty) BOOL empty;
|
@property (nonatomic, readonly, getter = isEmpty) BOOL empty;
|
||||||
|
|
||||||
|
|
@ -770,7 +792,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
|
|
||||||
@interface AFStreamingMultipartFormData ()
|
@interface AFStreamingMultipartFormData ()
|
||||||
@property (readwrite, nonatomic, copy) NSMutableURLRequest *request;
|
@property (readwrite, nonatomic, copy) NSMutableURLRequest *request;
|
||||||
@property (readwrite, nonatomic, strong) AFMultipartBodyStream *bodyStream;
|
@property (readwrite, nonatomic, strong) AFMultipartBodyStreamProvider *bodyStream;
|
||||||
@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
|
@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
@ -789,7 +811,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
|
|
||||||
self.request = urlRequest;
|
self.request = urlRequest;
|
||||||
self.stringEncoding = encoding;
|
self.stringEncoding = encoding;
|
||||||
self.bodyStream = [[AFMultipartBodyStream alloc] initWithStringEncoding:encoding];
|
self.bodyStream = [[AFMultipartBodyStreamProvider alloc] initWithStringEncoding:encoding];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
@ -801,6 +823,23 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
NSParameterAssert(fileURL);
|
NSParameterAssert(fileURL);
|
||||||
NSParameterAssert(name);
|
NSParameterAssert(name);
|
||||||
|
|
||||||
|
NSString *fileName = [fileURL lastPathComponent];
|
||||||
|
NSString *mimeType = AFContentTypeForPathExtension([fileURL pathExtension]);
|
||||||
|
|
||||||
|
return [self appendPartWithFileURL:fileURL name:name fileName:fileName mimeType:mimeType error:error];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
|
||||||
|
name:(NSString *)name
|
||||||
|
fileName:(NSString *)fileName
|
||||||
|
mimeType:(NSString *)mimeType
|
||||||
|
error:(NSError * __autoreleasing *)error
|
||||||
|
{
|
||||||
|
NSParameterAssert(fileURL);
|
||||||
|
NSParameterAssert(name);
|
||||||
|
NSParameterAssert(fileName);
|
||||||
|
NSParameterAssert(mimeType);
|
||||||
|
|
||||||
if (![fileURL isFileURL]) {
|
if (![fileURL isFileURL]) {
|
||||||
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedStringFromTable(@"Expected URL to be a file URL", @"AFNetworking", nil) forKey:NSLocalizedFailureReasonErrorKey];
|
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedStringFromTable(@"Expected URL to be a file URL", @"AFNetworking", nil) forKey:NSLocalizedFailureReasonErrorKey];
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
|
|
@ -818,8 +857,8 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
|
NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
|
||||||
[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, [fileURL lastPathComponent]] forKey:@"Content-Disposition"];
|
[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
|
||||||
[mutableHeaders setValue:AFContentTypeForPathExtension([fileURL pathExtension]) forKey:@"Content-Type"];
|
[mutableHeaders setValue:mimeType forKey:@"Content-Type"];
|
||||||
|
|
||||||
AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init];
|
AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init];
|
||||||
bodyPart.stringEncoding = self.stringEncoding;
|
bodyPart.stringEncoding = self.stringEncoding;
|
||||||
|
|
@ -834,6 +873,32 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)appendPartWithInputStream:(NSInputStream *)inputStream
|
||||||
|
name:(NSString *)name
|
||||||
|
fileName:(NSString *)fileName
|
||||||
|
length:(unsigned long long)length
|
||||||
|
mimeType:(NSString *)mimeType
|
||||||
|
{
|
||||||
|
NSParameterAssert(name);
|
||||||
|
NSParameterAssert(fileName);
|
||||||
|
NSParameterAssert(mimeType);
|
||||||
|
|
||||||
|
NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
|
||||||
|
[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
|
||||||
|
[mutableHeaders setValue:mimeType forKey:@"Content-Type"];
|
||||||
|
|
||||||
|
|
||||||
|
AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init];
|
||||||
|
bodyPart.stringEncoding = self.stringEncoding;
|
||||||
|
bodyPart.headers = mutableHeaders;
|
||||||
|
bodyPart.body = inputStream;
|
||||||
|
|
||||||
|
bodyPart.bodyContentLength = length;
|
||||||
|
|
||||||
|
[self.bodyStream appendHTTPBodyPart:bodyPart];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)appendPartWithFileData:(NSData *)data
|
- (void)appendPartWithFileData:(NSData *)data
|
||||||
name:(NSString *)name
|
name:(NSString *)name
|
||||||
fileName:(NSString *)fileName
|
fileName:(NSString *)fileName
|
||||||
|
|
@ -878,7 +943,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
- (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes
|
- (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes
|
||||||
delay:(NSTimeInterval)delay
|
delay:(NSTimeInterval)delay
|
||||||
{
|
{
|
||||||
self.bodyStream.numberOfBytesInPacket = numberOfBytes;
|
self.bodyStream.bufferLength = numberOfBytes;
|
||||||
self.bodyStream.delay = delay;
|
self.bodyStream.delay = delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -892,7 +957,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
|
|
||||||
[self.request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", kAFMultipartFormBoundary] forHTTPHeaderField:@"Content-Type"];
|
[self.request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", kAFMultipartFormBoundary] forHTTPHeaderField:@"Content-Type"];
|
||||||
[self.request setValue:[NSString stringWithFormat:@"%llu", [self.bodyStream contentLength]] forHTTPHeaderField:@"Content-Length"];
|
[self.request setValue:[NSString stringWithFormat:@"%llu", [self.bodyStream contentLength]] forHTTPHeaderField:@"Content-Length"];
|
||||||
[self.request setHTTPBodyStream:self.bodyStream];
|
[self.request setHTTPBodyStream:self.bodyStream.inputStream];
|
||||||
|
|
||||||
return self.request;
|
return self.request;
|
||||||
}
|
}
|
||||||
|
|
@ -901,24 +966,31 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
@interface AFMultipartBodyStream () <NSCopying>
|
@interface AFMultipartBodyStreamProvider () <NSCopying, NSStreamDelegate>
|
||||||
@property (nonatomic, assign) NSStreamStatus streamStatus;
|
|
||||||
@property (nonatomic, strong) NSError *streamError;
|
|
||||||
|
|
||||||
@property (nonatomic, assign) NSStringEncoding stringEncoding;
|
@property (nonatomic, assign) NSStringEncoding stringEncoding;
|
||||||
@property (nonatomic, strong) NSMutableArray *HTTPBodyParts;
|
@property (nonatomic, strong) NSMutableArray *HTTPBodyParts;
|
||||||
@property (nonatomic, strong) NSEnumerator *HTTPBodyPartEnumerator;
|
@property (nonatomic, strong) NSEnumerator *HTTPBodyPartEnumerator;
|
||||||
@property (nonatomic, strong) AFHTTPBodyPart *currentHTTPBodyPart;
|
@property (nonatomic, strong) AFHTTPBodyPart *currentHTTPBodyPart;
|
||||||
|
@property (nonatomic, strong) NSInputStream *inputStream;
|
||||||
|
@property (nonatomic, strong) NSOutputStream *outputStream;
|
||||||
|
@property (nonatomic, strong) NSMutableData *buffer;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation AFMultipartBodyStream
|
static const NSUInteger AFMultipartBodyStreamProviderDefaultBufferLength = 4096;
|
||||||
@synthesize streamStatus = _streamStatus;
|
|
||||||
@synthesize streamError = _streamError;
|
@implementation AFMultipartBodyStreamProvider {
|
||||||
|
@private
|
||||||
|
// Workaround for stream delegates being weakly referenced, but otherwise unowned
|
||||||
|
__strong id _self;
|
||||||
|
}
|
||||||
@synthesize stringEncoding = _stringEncoding;
|
@synthesize stringEncoding = _stringEncoding;
|
||||||
@synthesize HTTPBodyParts = _HTTPBodyParts;
|
@synthesize HTTPBodyParts = _HTTPBodyParts;
|
||||||
@synthesize HTTPBodyPartEnumerator = _HTTPBodyPartEnumerator;
|
@synthesize HTTPBodyPartEnumerator = _HTTPBodyPartEnumerator;
|
||||||
@synthesize currentHTTPBodyPart = _currentHTTPBodyPart;
|
@synthesize currentHTTPBodyPart = _currentHTTPBodyPart;
|
||||||
@synthesize numberOfBytesInPacket = _numberOfBytesInPacket;
|
@synthesize inputStream = _inputStream;
|
||||||
|
@synthesize outputStream = _outputStream;
|
||||||
|
@synthesize buffer = _buffer;
|
||||||
|
@synthesize bufferLength = _numberOfBytesInPacket;
|
||||||
@synthesize delay = _delay;
|
@synthesize delay = _delay;
|
||||||
|
|
||||||
- (id)initWithStringEncoding:(NSStringEncoding)encoding {
|
- (id)initWithStringEncoding:(NSStringEncoding)encoding {
|
||||||
|
|
@ -929,11 +1001,18 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
|
|
||||||
self.stringEncoding = encoding;
|
self.stringEncoding = encoding;
|
||||||
self.HTTPBodyParts = [NSMutableArray array];
|
self.HTTPBodyParts = [NSMutableArray array];
|
||||||
self.numberOfBytesInPacket = NSIntegerMax;
|
self.bufferLength = NSIntegerMax;
|
||||||
|
|
||||||
|
self.buffer = [[NSMutableData alloc] init];
|
||||||
|
self.bufferLength = AFMultipartBodyStreamProviderDefaultBufferLength;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
_outputStream.delegate = nil;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setInitialAndFinalBoundaries {
|
- (void)setInitialAndFinalBoundaries {
|
||||||
if ([self.HTTPBodyParts count] > 0) {
|
if ([self.HTTPBodyParts count] > 0) {
|
||||||
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
|
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
|
||||||
|
|
@ -950,80 +1029,95 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
[self.HTTPBodyParts addObject:bodyPart];
|
[self.HTTPBodyParts addObject:bodyPart];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSInputStream *)inputStream {
|
||||||
|
if (_inputStream == nil) {
|
||||||
|
CFReadStreamRef readStream;
|
||||||
|
CFWriteStreamRef writeStream;
|
||||||
|
CFStreamCreateBoundPair(NULL, &readStream, &writeStream, self.bufferLength);
|
||||||
|
_inputStream = CFBridgingRelease(readStream);
|
||||||
|
_outputStream = CFBridgingRelease(writeStream);
|
||||||
|
|
||||||
|
_outputStream.delegate = self;
|
||||||
|
if ([NSThread isMainThread]) {
|
||||||
|
[_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||||
|
} else {
|
||||||
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||||
|
[_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
[_outputStream open];
|
||||||
|
|
||||||
|
_self = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)isEmpty {
|
- (BOOL)isEmpty {
|
||||||
return [self.HTTPBodyParts count] == 0;
|
return [self.HTTPBodyParts count] == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - NSInputStream
|
#pragma mark - NSStreamDelegate
|
||||||
|
|
||||||
- (NSInteger)read:(uint8_t *)buffer
|
- (void)stream:(NSStream *)stream
|
||||||
maxLength:(NSUInteger)length
|
handleEvent:(NSStreamEvent)eventCode
|
||||||
{
|
{
|
||||||
if ([self streamStatus] == NSStreamStatusClosed) {
|
if (eventCode & NSStreamEventHasSpaceAvailable) {
|
||||||
return 0;
|
[self handleOutputStreamSpaceAvailable];
|
||||||
}
|
}
|
||||||
NSInteger bytesRead = 0;
|
}
|
||||||
|
|
||||||
while ((NSUInteger)bytesRead < MIN(length, self.numberOfBytesInPacket)) {
|
- (void)handleOutputStreamSpaceAvailable {
|
||||||
if (!self.currentHTTPBodyPart || ![self.currentHTTPBodyPart hasBytesAvailable]) {
|
while ([_outputStream hasSpaceAvailable]) {
|
||||||
if (!(self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject])) {
|
if ([_buffer length] > 0) {
|
||||||
break;
|
NSInteger numberOfBytesWritten = [_outputStream write:[_buffer bytes] maxLength:[_buffer length]];
|
||||||
|
if (numberOfBytesWritten < 0) {
|
||||||
|
[self close];
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[_buffer replaceBytesInRange:NSMakeRange(0, numberOfBytesWritten) withBytes:NULL length:0];
|
||||||
} else {
|
} else {
|
||||||
bytesRead += [self.currentHTTPBodyPart read:&buffer[bytesRead] maxLength:(length - (NSUInteger)bytesRead)];
|
if (!self.currentHTTPBodyPart) {
|
||||||
|
if (!self.HTTPBodyPartEnumerator) {
|
||||||
|
self.HTTPBodyPartEnumerator = [self.HTTPBodyParts objectEnumerator];
|
||||||
|
}
|
||||||
|
self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self.currentHTTPBodyPart) {
|
||||||
|
[self close];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[_buffer setLength:self.bufferLength];
|
||||||
|
|
||||||
|
NSInteger numberOfBytesRead = [self.currentHTTPBodyPart read:[_buffer mutableBytes] maxLength:[_buffer length]];
|
||||||
|
if (numberOfBytesRead < 0) {
|
||||||
|
[self close];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[_buffer setLength:numberOfBytesRead];
|
||||||
|
|
||||||
|
if(numberOfBytesRead == 0) {
|
||||||
|
self.currentHTTPBodyPart = nil;
|
||||||
|
}
|
||||||
|
|
||||||
if (self.delay > 0.0f) {
|
if (self.delay > 0.0f) {
|
||||||
[NSThread sleepForTimeInterval:self.delay];
|
[NSThread sleepForTimeInterval:self.delay];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bytesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)getBuffer:(__unused uint8_t **)buffer
|
|
||||||
length:(__unused NSUInteger *)len
|
|
||||||
{
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)hasBytesAvailable {
|
|
||||||
return [self streamStatus] == NSStreamStatusOpen;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - NSStream
|
|
||||||
|
|
||||||
- (void)open {
|
|
||||||
if (self.streamStatus == NSStreamStatusOpen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.streamStatus = NSStreamStatusOpen;
|
|
||||||
|
|
||||||
[self setInitialAndFinalBoundaries];
|
|
||||||
self.HTTPBodyPartEnumerator = [self.HTTPBodyParts objectEnumerator];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)close {
|
- (void)close {
|
||||||
self.streamStatus = NSStreamStatusClosed;
|
[_outputStream close];
|
||||||
|
_outputStream.delegate = nil;
|
||||||
|
|
||||||
|
_self = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)propertyForKey:(__unused NSString *)key {
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)setProperty:(__unused id)property
|
|
||||||
forKey:(__unused NSString *)key
|
|
||||||
{
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)scheduleInRunLoop:(__unused NSRunLoop *)aRunLoop
|
|
||||||
forMode:(__unused NSString *)mode
|
|
||||||
{}
|
|
||||||
|
|
||||||
- (void)removeFromRunLoop:(__unused NSRunLoop *)aRunLoop
|
|
||||||
forMode:(__unused NSString *)mode
|
|
||||||
{}
|
|
||||||
|
|
||||||
- (unsigned long long)contentLength {
|
- (unsigned long long)contentLength {
|
||||||
unsigned long long length = 0;
|
unsigned long long length = 0;
|
||||||
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
|
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
|
||||||
|
|
@ -1033,26 +1127,10 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Undocumented CFReadStream Bridged Methods
|
|
||||||
|
|
||||||
- (void)_scheduleInCFRunLoop:(__unused CFRunLoopRef)aRunLoop
|
|
||||||
forMode:(__unused CFStringRef)aMode
|
|
||||||
{}
|
|
||||||
|
|
||||||
- (void)_unscheduleFromCFRunLoop:(__unused CFRunLoopRef)aRunLoop
|
|
||||||
forMode:(__unused CFStringRef)aMode
|
|
||||||
{}
|
|
||||||
|
|
||||||
- (BOOL)_setCFClientFlags:(__unused CFOptionFlags)inFlags
|
|
||||||
callback:(__unused CFReadStreamClientCallBack)inCallback
|
|
||||||
context:(__unused CFStreamClientContext *)inContext {
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - NSCopying
|
#pragma mark - NSCopying
|
||||||
|
|
||||||
-(id)copyWithZone:(NSZone *)zone {
|
- (id)copyWithZone:(NSZone *)zone {
|
||||||
AFMultipartBodyStream *bodyStreamCopy = [[[self class] allocWithZone:zone] initWithStringEncoding:self.stringEncoding];
|
AFMultipartBodyStreamProvider *bodyStreamCopy = [[[self class] allocWithZone:zone] initWithStringEncoding:self.stringEncoding];
|
||||||
|
|
||||||
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
|
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
|
||||||
[bodyStreamCopy appendHTTPBodyPart:[bodyPart copy]];
|
[bodyStreamCopy appendHTTPBodyPart:[bodyPart copy]];
|
||||||
|
|
@ -1068,10 +1146,12 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
AFInitialPhase = 0,
|
||||||
AFEncapsulationBoundaryPhase = 1,
|
AFEncapsulationBoundaryPhase = 1,
|
||||||
AFHeaderPhase = 2,
|
AFHeaderPhase = 2,
|
||||||
AFBodyPhase = 3,
|
AFBodyPhase = 3,
|
||||||
AFFinalBoundaryPhase = 4,
|
AFFinalBoundaryPhase = 4,
|
||||||
|
AFCompletedPhase = 5,
|
||||||
} AFHTTPBodyPartReadPhase;
|
} AFHTTPBodyPartReadPhase;
|
||||||
|
|
||||||
@interface AFHTTPBodyPart () <NSCopying> {
|
@interface AFHTTPBodyPart () <NSCopying> {
|
||||||
|
|
@ -1118,6 +1198,8 @@ typedef enum {
|
||||||
_inputStream = [NSInputStream inputStreamWithData:self.body];
|
_inputStream = [NSInputStream inputStreamWithData:self.body];
|
||||||
} else if ([self.body isKindOfClass:[NSURL class]]) {
|
} else if ([self.body isKindOfClass:[NSURL class]]) {
|
||||||
_inputStream = [NSInputStream inputStreamWithURL:self.body];
|
_inputStream = [NSInputStream inputStreamWithURL:self.body];
|
||||||
|
} else if ([self.body isKindOfClass:[NSInputStream class]]) {
|
||||||
|
_inputStream = self.body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1152,11 +1234,13 @@ typedef enum {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)hasBytesAvailable {
|
- (BOOL)hasBytesAvailable {
|
||||||
// Allows `read:maxLength:` to be called again if `AFMultipartFormFinalBoundary` doesn't fit into the avaiable buffer
|
// Allows `read:maxLength:` to be called again if `AFMultipartFormFinalBoundary` doesn't fit into the available buffer
|
||||||
if (_phase == AFFinalBoundaryPhase) {
|
if (_phase == AFFinalBoundaryPhase) {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||||
switch (self.inputStream.streamStatus) {
|
switch (self.inputStream.streamStatus) {
|
||||||
case NSStreamStatusNotOpen:
|
case NSStreamStatusNotOpen:
|
||||||
case NSStreamStatusOpening:
|
case NSStreamStatusOpening:
|
||||||
|
|
@ -1170,6 +1254,8 @@ typedef enum {
|
||||||
default:
|
default:
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSInteger)read:(uint8_t *)buffer
|
- (NSInteger)read:(uint8_t *)buffer
|
||||||
|
|
@ -1227,7 +1313,12 @@ typedef enum {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||||
switch (_phase) {
|
switch (_phase) {
|
||||||
|
case AFInitialPhase:
|
||||||
|
_phase = AFEncapsulationBoundaryPhase;
|
||||||
|
break;
|
||||||
case AFEncapsulationBoundaryPhase:
|
case AFEncapsulationBoundaryPhase:
|
||||||
_phase = AFHeaderPhase;
|
_phase = AFHeaderPhase;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1241,10 +1332,13 @@ typedef enum {
|
||||||
_phase = AFFinalBoundaryPhase;
|
_phase = AFFinalBoundaryPhase;
|
||||||
break;
|
break;
|
||||||
case AFFinalBoundaryPhase:
|
case AFFinalBoundaryPhase:
|
||||||
_phase = AFEncapsulationBoundaryPhase;
|
case AFCompletedPhase:
|
||||||
|
default:
|
||||||
|
_phase = AFCompletedPhase;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_phaseReadOffset = 0;
|
_phaseReadOffset = 0;
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@
|
||||||
#define AF_CAST_TO_BLOCK __bridge void *
|
#define AF_CAST_TO_BLOCK __bridge void *
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// We do a little bit of duck typing in this file which can trigger this warning. Turn it off for this source file.
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wstrict-selector-match"
|
#pragma clang diagnostic ignored "-Wstrict-selector-match"
|
||||||
|
|
||||||
|
|
@ -108,18 +107,12 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL
|
||||||
@property (readwrite, nonatomic, strong) NSURLRequest *request;
|
@property (readwrite, nonatomic, strong) NSURLRequest *request;
|
||||||
@property (readwrite, nonatomic, strong) NSHTTPURLResponse *response;
|
@property (readwrite, nonatomic, strong) NSHTTPURLResponse *response;
|
||||||
@property (readwrite, nonatomic, strong) NSError *HTTPError;
|
@property (readwrite, nonatomic, strong) NSError *HTTPError;
|
||||||
@property (readwrite, nonatomic, copy) NSString *HTTPResponseString;
|
|
||||||
@property (readwrite, nonatomic, assign) long long totalContentLength;
|
|
||||||
@property (readwrite, nonatomic, assign) long long offsetContentLength;
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation AFHTTPRequestOperation
|
@implementation AFHTTPRequestOperation
|
||||||
@synthesize HTTPError = _HTTPError;
|
@synthesize HTTPError = _HTTPError;
|
||||||
@synthesize HTTPResponseString = _HTTPResponseString;
|
|
||||||
@synthesize successCallbackQueue = _successCallbackQueue;
|
@synthesize successCallbackQueue = _successCallbackQueue;
|
||||||
@synthesize failureCallbackQueue = _failureCallbackQueue;
|
@synthesize failureCallbackQueue = _failureCallbackQueue;
|
||||||
@synthesize totalContentLength = _totalContentLength;
|
|
||||||
@synthesize offsetContentLength = _offsetContentLength;
|
|
||||||
@dynamic request;
|
@dynamic request;
|
||||||
@dynamic response;
|
@dynamic response;
|
||||||
|
|
||||||
|
|
@ -169,23 +162,19 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)responseString {
|
- (NSStringEncoding)responseStringEncoding {
|
||||||
// When no explicit charset parameter is provided by the sender, media subtypes of the "text" type are defined to have a default charset value of "ISO-8859-1" when received via HTTP. Data in character sets other than "ISO-8859-1" or its subsets MUST be labeled with an appropriate charset value.
|
// When no explicit charset parameter is provided by the sender, media subtypes of the "text" type are defined to have a default charset value of "ISO-8859-1" when received via HTTP. Data in character sets other than "ISO-8859-1" or its subsets MUST be labeled with an appropriate charset value.
|
||||||
// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.4.1
|
// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.4.1
|
||||||
if (!self.HTTPResponseString && self.response && !self.response.textEncodingName && self.responseData) {
|
if (self.response && !self.response.textEncodingName && self.responseData) {
|
||||||
NSString *type = nil;
|
NSString *type = nil;
|
||||||
AFGetMediaTypeAndSubtypeWithString([[self.response allHeaderFields] valueForKey:@"Content-Type"], &type, nil);
|
AFGetMediaTypeAndSubtypeWithString([[self.response allHeaderFields] valueForKey:@"Content-Type"], &type, nil);
|
||||||
|
|
||||||
if ([type isEqualToString:@"text"]) {
|
if ([type isEqualToString:@"text"]) {
|
||||||
self.HTTPResponseString = [[NSString alloc] initWithData:self.responseData encoding:NSISOLatin1StringEncoding];
|
return NSISOLatin1StringEncoding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.HTTPResponseString) {
|
return [super responseStringEncoding];
|
||||||
return self.HTTPResponseString;
|
|
||||||
} else {
|
|
||||||
return [super responseString];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)pause {
|
- (void)pause {
|
||||||
|
|
@ -324,46 +313,6 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL
|
||||||
return [[self acceptableContentTypes] intersectsSet:AFContentTypesFromHTTPHeader([request valueForHTTPHeaderField:@"Accept"])];
|
return [[self acceptableContentTypes] intersectsSet:AFContentTypesFromHTTPHeader([request valueForHTTPHeaderField:@"Accept"])];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - NSURLConnectionDelegate
|
|
||||||
|
|
||||||
- (void)connection:(__unused NSURLConnection *)connection
|
|
||||||
didReceiveResponse:(NSURLResponse *)response
|
|
||||||
{
|
|
||||||
self.response = (NSHTTPURLResponse *)response;
|
|
||||||
|
|
||||||
// Set Content-Range header if status code of response is 206 (Partial Content)
|
|
||||||
// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.7
|
|
||||||
long long totalContentLength = self.response.expectedContentLength;
|
|
||||||
long long fileOffset = 0;
|
|
||||||
NSUInteger statusCode = ([self.response isKindOfClass:[NSHTTPURLResponse class]]) ? (NSUInteger)[self.response statusCode] : 200;
|
|
||||||
if (statusCode == 206) {
|
|
||||||
NSString *contentRange = [self.response.allHeaderFields valueForKey:@"Content-Range"];
|
|
||||||
if ([contentRange hasPrefix:@"bytes"]) {
|
|
||||||
NSArray *byteRanges = [contentRange componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" -/"]];
|
|
||||||
if ([byteRanges count] == 4) {
|
|
||||||
fileOffset = [[byteRanges objectAtIndex:1] longLongValue];
|
|
||||||
totalContentLength = [[byteRanges objectAtIndex:2] longLongValue] ?: -1; // if this is "*", it's converted to 0, but -1 is default.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ([self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey]) {
|
|
||||||
[self.outputStream setProperty:[NSNumber numberWithInteger:0] forKey:NSStreamFileCurrentOffsetKey];
|
|
||||||
} else {
|
|
||||||
if ([[self.outputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey] length] > 0) {
|
|
||||||
self.outputStream = [NSOutputStream outputStreamToMemory];
|
|
||||||
|
|
||||||
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
|
||||||
for (NSString *runLoopMode in self.runLoopModes) {
|
|
||||||
[self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.offsetContentLength = MAX(fileOffset, 0);
|
|
||||||
self.totalContentLength = totalContentLength;
|
|
||||||
|
|
||||||
[self.outputStream open];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,12 @@
|
||||||
|
|
||||||
#import "AFImageRequestOperation.h"
|
#import "AFImageRequestOperation.h"
|
||||||
|
|
||||||
static dispatch_queue_t af_image_request_operation_processing_queue;
|
|
||||||
static dispatch_queue_t image_request_operation_processing_queue() {
|
static dispatch_queue_t image_request_operation_processing_queue() {
|
||||||
if (af_image_request_operation_processing_queue == NULL) {
|
static dispatch_queue_t af_image_request_operation_processing_queue;
|
||||||
af_image_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.image-request.processing", 0);
|
static dispatch_once_t onceToken;
|
||||||
}
|
dispatch_once(&onceToken, ^{
|
||||||
|
af_image_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.image-request.processing", DISPATCH_QUEUE_CONCURRENT);
|
||||||
|
});
|
||||||
|
|
||||||
return af_image_request_operation_processing_queue;
|
return af_image_request_operation_processing_queue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,12 @@
|
||||||
|
|
||||||
#import "AFJSONRequestOperation.h"
|
#import "AFJSONRequestOperation.h"
|
||||||
|
|
||||||
static dispatch_queue_t af_json_request_operation_processing_queue;
|
|
||||||
static dispatch_queue_t json_request_operation_processing_queue() {
|
static dispatch_queue_t json_request_operation_processing_queue() {
|
||||||
if (af_json_request_operation_processing_queue == NULL) {
|
static dispatch_queue_t af_json_request_operation_processing_queue;
|
||||||
af_json_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.json-request.processing", 0);
|
static dispatch_once_t onceToken;
|
||||||
}
|
dispatch_once(&onceToken, ^{
|
||||||
|
af_json_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.json-request.processing", DISPATCH_QUEUE_CONCURRENT);
|
||||||
|
});
|
||||||
|
|
||||||
return af_json_request_operation_processing_queue;
|
return af_json_request_operation_processing_queue;
|
||||||
}
|
}
|
||||||
|
|
@ -34,12 +35,14 @@ static dispatch_queue_t json_request_operation_processing_queue() {
|
||||||
@interface AFJSONRequestOperation ()
|
@interface AFJSONRequestOperation ()
|
||||||
@property (readwrite, nonatomic, strong) id responseJSON;
|
@property (readwrite, nonatomic, strong) id responseJSON;
|
||||||
@property (readwrite, nonatomic, strong) NSError *JSONError;
|
@property (readwrite, nonatomic, strong) NSError *JSONError;
|
||||||
|
@property (readwrite, nonatomic, strong) NSRecursiveLock *lock;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation AFJSONRequestOperation
|
@implementation AFJSONRequestOperation
|
||||||
@synthesize responseJSON = _responseJSON;
|
@synthesize responseJSON = _responseJSON;
|
||||||
@synthesize JSONReadingOptions = _JSONReadingOptions;
|
@synthesize JSONReadingOptions = _JSONReadingOptions;
|
||||||
@synthesize JSONError = _JSONError;
|
@synthesize JSONError = _JSONError;
|
||||||
|
@dynamic lock;
|
||||||
|
|
||||||
+ (instancetype)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
+ (instancetype)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest
|
||||||
success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success
|
success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success
|
||||||
|
|
@ -61,6 +64,7 @@ static dispatch_queue_t json_request_operation_processing_queue() {
|
||||||
|
|
||||||
|
|
||||||
- (id)responseJSON {
|
- (id)responseJSON {
|
||||||
|
[self.lock lock];
|
||||||
if (!_responseJSON && [self.responseData length] > 0 && [self isFinished] && !self.JSONError) {
|
if (!_responseJSON && [self.responseData length] > 0 && [self isFinished] && !self.JSONError) {
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
|
||||||
|
|
@ -77,6 +81,7 @@ static dispatch_queue_t json_request_operation_processing_queue() {
|
||||||
|
|
||||||
self.JSONError = error;
|
self.JSONError = error;
|
||||||
}
|
}
|
||||||
|
[self.lock unlock];
|
||||||
|
|
||||||
return _responseJSON;
|
return _responseJSON;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,8 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.17;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(incrementActivityCount) name:AFNetworkingOperationDidStartNotification object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkingOperationDidStart:) name:AFNetworkingOperationDidStartNotification object:nil];
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(decrementActivityCount) name:AFNetworkingOperationDidFinishNotification object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkingOperationDidFinish:) name:AFNetworkingOperationDidFinishNotification object:nil];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
@ -126,6 +126,20 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.17;
|
||||||
[self updateNetworkActivityIndicatorVisibilityDelayed];
|
[self updateNetworkActivityIndicatorVisibilityDelayed];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)networkingOperationDidStart:(NSNotification *)notification {
|
||||||
|
AFURLConnectionOperation *connectionOperation = [notification object];
|
||||||
|
if (connectionOperation.request.URL) {
|
||||||
|
[self incrementActivityCount];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)networkingOperationDidFinish:(NSNotification *)notification {
|
||||||
|
AFURLConnectionOperation *connectionOperation = [notification object];
|
||||||
|
if (connectionOperation.request.URL) {
|
||||||
|
[self decrementActivityCount];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,12 @@
|
||||||
|
|
||||||
#import "AFPropertyListRequestOperation.h"
|
#import "AFPropertyListRequestOperation.h"
|
||||||
|
|
||||||
static dispatch_queue_t af_property_list_request_operation_processing_queue;
|
|
||||||
static dispatch_queue_t property_list_request_operation_processing_queue() {
|
static dispatch_queue_t property_list_request_operation_processing_queue() {
|
||||||
if (af_property_list_request_operation_processing_queue == NULL) {
|
static dispatch_queue_t af_property_list_request_operation_processing_queue;
|
||||||
af_property_list_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.property-list-request.processing", 0);
|
static dispatch_once_t onceToken;
|
||||||
}
|
dispatch_once(&onceToken, ^{
|
||||||
|
af_property_list_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.property-list-request.processing", DISPATCH_QUEUE_CONCURRENT);
|
||||||
|
});
|
||||||
|
|
||||||
return af_property_list_request_operation_processing_queue;
|
return af_property_list_request_operation_processing_queue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,14 @@
|
||||||
The built-in `completionBlock` provided by `NSOperation` allows for custom behavior to be executed after the request finishes. It is a common pattern for class constructors in subclasses to take callback block parameters, and execute them conditionally in the body of its `completionBlock`. Make sure to handle cancelled operations appropriately when setting a `completionBlock` (i.e. returning early before parsing response data). See the implementation of any of the `AFHTTPRequestOperation` subclasses for an example of this.
|
The built-in `completionBlock` provided by `NSOperation` allows for custom behavior to be executed after the request finishes. It is a common pattern for class constructors in subclasses to take callback block parameters, and execute them conditionally in the body of its `completionBlock`. Make sure to handle cancelled operations appropriately when setting a `completionBlock` (i.e. returning early before parsing response data). See the implementation of any of the `AFHTTPRequestOperation` subclasses for an example of this.
|
||||||
|
|
||||||
Subclasses are strongly discouraged from overriding `setCompletionBlock:`, as `AFURLConnectionOperation`'s implementation includes a workaround to mitigate retain cycles, and what Apple rather ominously refers to as ["The Deallocation Problem"](http://developer.apple.com/library/ios/#technotes/tn2109/).
|
Subclasses are strongly discouraged from overriding `setCompletionBlock:`, as `AFURLConnectionOperation`'s implementation includes a workaround to mitigate retain cycles, and what Apple rather ominously refers to as ["The Deallocation Problem"](http://developer.apple.com/library/ios/#technotes/tn2109/).
|
||||||
|
|
||||||
|
## SSL Pinning
|
||||||
|
|
||||||
|
Relying on the CA trust model to validate SSL certificates exposes your app to security vulnerabilities, such as man-in-the-middle attacks. For applications that connect to known servers, SSL certificate pinning provides an increased level of security, by checking server certificate validity against those specified in the app bundle.
|
||||||
|
|
||||||
|
SSL with certificate pinning is strongly recommended for any application that transmits sensitive information to an external webservice.
|
||||||
|
|
||||||
|
When `_AFNETWORKING_PIN_SSL_CERTIFICATES_` is defined and the Security framework is linked, connections will be validated on all matching certificates with a `.cer` extension in the bundle root.
|
||||||
|
|
||||||
## NSCoding & NSCopying Conformance
|
## NSCoding & NSCopying Conformance
|
||||||
|
|
||||||
|
|
@ -75,7 +83,21 @@
|
||||||
- A copy of an operation will not include the `outputStream` of the original.
|
- A copy of an operation will not include the `outputStream` of the original.
|
||||||
- Operation copies do not include `completionBlock`. `completionBlock` often strongly captures a reference to `self`, which would otherwise have the unintuitive side-effect of pointing to the _original_ operation when copied.
|
- Operation copies do not include `completionBlock`. `completionBlock` often strongly captures a reference to `self`, which would otherwise have the unintuitive side-effect of pointing to the _original_ operation when copied.
|
||||||
*/
|
*/
|
||||||
@interface AFURLConnectionOperation : NSOperation <NSURLConnectionDelegate, NSCoding, NSCopying>
|
|
||||||
|
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
typedef enum {
|
||||||
|
AFSSLPinningModeNone,
|
||||||
|
AFSSLPinningModePublicKey,
|
||||||
|
AFSSLPinningModeCertificate,
|
||||||
|
} AFURLConnectionOperationSSLPinningMode;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@interface AFURLConnectionOperation : NSOperation <NSURLConnectionDelegate,
|
||||||
|
#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_5_0) || \
|
||||||
|
(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_8)
|
||||||
|
NSURLConnectionDataDelegate,
|
||||||
|
#endif
|
||||||
|
NSCoding, NSCopying>
|
||||||
|
|
||||||
///-------------------------------
|
///-------------------------------
|
||||||
/// @name Accessing Run Loop Modes
|
/// @name Accessing Run Loop Modes
|
||||||
|
|
@ -131,7 +153,6 @@
|
||||||
*/
|
*/
|
||||||
@property (readonly, nonatomic, assign) NSStringEncoding responseStringEncoding;
|
@property (readonly, nonatomic, assign) NSStringEncoding responseStringEncoding;
|
||||||
|
|
||||||
|
|
||||||
///-------------------------------
|
///-------------------------------
|
||||||
/// @name Managing URL Credentials
|
/// @name Managing URL Credentials
|
||||||
///-------------------------------
|
///-------------------------------
|
||||||
|
|
@ -150,6 +171,15 @@
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, strong) NSURLCredential *credential;
|
@property (nonatomic, strong) NSURLCredential *credential;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The pinning mode which will be used for SSL connections. `AFSSLPinningModePublicKey` by default.
|
||||||
|
|
||||||
|
@discussion To enable SSL Pinning, `#define _AFNETWORKING_PIN_SSL_CERTIFICATES_` in `Prefix.pch`. Also, make sure that the Security framework is linked with the binary. See the "SSL Pinning" section in the `AFURLConnectionOperation`" header for more information.
|
||||||
|
*/
|
||||||
|
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
@property (nonatomic, assign) AFURLConnectionOperationSSLPinningMode SSLPinningMode;
|
||||||
|
#endif
|
||||||
|
|
||||||
///------------------------
|
///------------------------
|
||||||
/// @name Accessing Streams
|
/// @name Accessing Streams
|
||||||
///------------------------
|
///------------------------
|
||||||
|
|
@ -290,6 +320,25 @@
|
||||||
///----------------
|
///----------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
## SSL Pinning Options
|
||||||
|
|
||||||
|
The following constants are provided by `AFURLConnectionOperation` as possible SSL Pinning options.
|
||||||
|
|
||||||
|
enum {
|
||||||
|
AFSSLPinningModeNone,
|
||||||
|
AFSSLPinningModePublicKey,
|
||||||
|
AFSSLPinningModeCertificate,
|
||||||
|
}
|
||||||
|
|
||||||
|
`AFSSLPinningModeNone`
|
||||||
|
Do not pin SSL connections
|
||||||
|
|
||||||
|
`AFSSLPinningModePublicKey`
|
||||||
|
Pin SSL connections to certificate public key (SPKI).
|
||||||
|
|
||||||
|
`AFSSLPinningModeCertificate`
|
||||||
|
Pin SSL connections to exact certificate. This may cause problems when your certificate expires and needs re-issuance.
|
||||||
|
|
||||||
## User info dictionary keys
|
## User info dictionary keys
|
||||||
|
|
||||||
These keys may exist in the user info dictionary, in addition to those defined for NSError.
|
These keys may exist in the user info dictionary, in addition to those defined for NSError.
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,9 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
@dynamic inputStream;
|
@dynamic inputStream;
|
||||||
@synthesize outputStream = _outputStream;
|
@synthesize outputStream = _outputStream;
|
||||||
@synthesize credential = _credential;
|
@synthesize credential = _credential;
|
||||||
|
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
@synthesize SSLPinningMode = _SSLPinningMode;
|
||||||
|
#endif
|
||||||
@synthesize shouldUseCredentialStorage = _shouldUseCredentialStorage;
|
@synthesize shouldUseCredentialStorage = _shouldUseCredentialStorage;
|
||||||
@synthesize userInfo = _userInfo;
|
@synthesize userInfo = _userInfo;
|
||||||
@synthesize backgroundTaskIdentifier = _backgroundTaskIdentifier;
|
@synthesize backgroundTaskIdentifier = _backgroundTaskIdentifier;
|
||||||
|
|
@ -167,7 +170,6 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
+ (NSThread *)networkRequestThread {
|
+ (NSThread *)networkRequestThread {
|
||||||
static NSThread *_networkRequestThread = nil;
|
static NSThread *_networkRequestThread = nil;
|
||||||
static dispatch_once_t oncePredicate;
|
static dispatch_once_t oncePredicate;
|
||||||
|
|
||||||
dispatch_once(&oncePredicate, ^{
|
dispatch_once(&oncePredicate, ^{
|
||||||
_networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
|
_networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
|
||||||
[_networkRequestThread start];
|
[_networkRequestThread start];
|
||||||
|
|
@ -176,24 +178,61 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
return _networkRequestThread;
|
return _networkRequestThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
+ (NSArray *)pinnedCertificates {
|
+ (NSArray *)pinnedCertificates {
|
||||||
static NSArray *_pinnedCertificates = nil;
|
static NSArray *_pinnedCertificates = nil;
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
|
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
||||||
NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."];
|
NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."];
|
||||||
NSMutableArray *certificates = [NSMutableArray array];
|
|
||||||
|
NSMutableArray *certificates = [NSMutableArray arrayWithCapacity:[paths count]];
|
||||||
for (NSString *path in paths) {
|
for (NSString *path in paths) {
|
||||||
NSData *certificateData = [NSData dataWithContentsOfFile:path];
|
NSData *certificateData = [NSData dataWithContentsOfFile:path];
|
||||||
[certificates addObject:certificateData];
|
[certificates addObject:certificateData];
|
||||||
}
|
}
|
||||||
|
|
||||||
_pinnedCertificates = [[NSArray alloc] initWithArray:certificates];
|
_pinnedCertificates = [[NSArray alloc] initWithArray:certificates];
|
||||||
});
|
});
|
||||||
|
|
||||||
return _pinnedCertificates;
|
return _pinnedCertificates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (NSArray *)pinnedPublicKeys {
|
||||||
|
static NSArray *_pinnedPublicKeys = nil;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
NSArray *pinnedCertificates = [self pinnedCertificates];
|
||||||
|
NSMutableArray *publicKeys = [NSMutableArray arrayWithCapacity:[pinnedCertificates count]];
|
||||||
|
|
||||||
|
for (NSData *data in pinnedCertificates) {
|
||||||
|
SecCertificateRef allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data);
|
||||||
|
NSCParameterAssert(allowedCertificate);
|
||||||
|
|
||||||
|
SecCertificateRef allowedCertificates[] = {allowedCertificate};
|
||||||
|
CFArrayRef certificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL);
|
||||||
|
|
||||||
|
SecPolicyRef policy = SecPolicyCreateBasicX509();
|
||||||
|
SecTrustRef allowedTrust = NULL;
|
||||||
|
OSStatus status = SecTrustCreateWithCertificates(certificates, policy, &allowedTrust);
|
||||||
|
NSAssert(status == noErr, @"SecTrustCreateWithCertificates error: %ld", (long int)status);
|
||||||
|
|
||||||
|
SecKeyRef allowedPublicKey = SecTrustCopyPublicKey(allowedTrust);
|
||||||
|
[publicKeys addObject:(__bridge_transfer id)allowedPublicKey];
|
||||||
|
|
||||||
|
CFRelease(allowedTrust);
|
||||||
|
CFRelease(policy);
|
||||||
|
CFRelease(certificates);
|
||||||
|
CFRelease(allowedCertificate);
|
||||||
|
}
|
||||||
|
|
||||||
|
_pinnedPublicKeys = [[NSArray alloc] initWithArray:publicKeys];
|
||||||
|
});
|
||||||
|
|
||||||
|
return _pinnedPublicKeys;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
- (id)initWithRequest:(NSURLRequest *)urlRequest {
|
- (id)initWithRequest:(NSURLRequest *)urlRequest {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (!self) {
|
if (!self) {
|
||||||
|
|
@ -344,19 +383,6 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
[self didChangeValueForKey:oldStateKey];
|
[self didChangeValueForKey:oldStateKey];
|
||||||
[self didChangeValueForKey:newStateKey];
|
[self didChangeValueForKey:newStateKey];
|
||||||
[self.lock unlock];
|
[self.lock unlock];
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
|
||||||
switch (state) {
|
|
||||||
case AFOperationExecutingState:
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidStartNotification object:self];
|
|
||||||
break;
|
|
||||||
case AFOperationFinishedState:
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)responseString {
|
- (NSString *)responseString {
|
||||||
|
|
@ -371,7 +397,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
|
|
||||||
- (NSStringEncoding)responseStringEncoding {
|
- (NSStringEncoding)responseStringEncoding {
|
||||||
[self.lock lock];
|
[self.lock lock];
|
||||||
if (!_responseStringEncoding) {
|
if (!_responseStringEncoding && self.response) {
|
||||||
NSStringEncoding stringEncoding = NSUTF8StringEncoding;
|
NSStringEncoding stringEncoding = NSUTF8StringEncoding;
|
||||||
if (self.response.textEncodingName) {
|
if (self.response.textEncodingName) {
|
||||||
CFStringEncoding IANAEncoding = CFStringConvertIANACharSetNameToEncoding((__bridge CFStringRef)self.response.textEncodingName);
|
CFStringEncoding IANAEncoding = CFStringConvertIANACharSetNameToEncoding((__bridge CFStringRef)self.response.textEncodingName);
|
||||||
|
|
@ -398,7 +424,8 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
[self.connection performSelector:@selector(cancel) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
|
[self.connection performSelector:@selector(cancel) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
|
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||||
|
[notificationCenter postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -453,24 +480,34 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
|
|
||||||
- (void)operationDidStart {
|
- (void)operationDidStart {
|
||||||
[self.lock lock];
|
[self.lock lock];
|
||||||
if ([self isCancelled]) {
|
if (! [self isCancelled]) {
|
||||||
[self finish];
|
|
||||||
} else {
|
|
||||||
self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO];
|
self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO];
|
||||||
|
|
||||||
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
||||||
for (NSString *runLoopMode in self.runLoopModes) {
|
for (NSString *runLoopMode in self.runLoopModes) {
|
||||||
[self.connection scheduleInRunLoop:runLoop forMode:runLoopMode];
|
[self.connection scheduleInRunLoop:runLoop forMode:runLoopMode];
|
||||||
[self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode];
|
[self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self.connection start];
|
[self.connection start];
|
||||||
}
|
}
|
||||||
[self.lock unlock];
|
[self.lock unlock];
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidStartNotification object:self];
|
||||||
|
});
|
||||||
|
|
||||||
|
if ([self isCancelled]) {
|
||||||
|
[self finish];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)finish {
|
- (void)finish {
|
||||||
self.state = AFOperationFinishedState;
|
self.state = AFOperationFinishedState;
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)cancel {
|
- (void)cancel {
|
||||||
|
|
@ -517,12 +554,57 @@ willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challe
|
||||||
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
||||||
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
||||||
} else {
|
} else {
|
||||||
[[challenge sender] cancelAuthenticationChallenge:challenge];
|
switch (self.SSLPinningMode) {
|
||||||
|
case AFSSLPinningModePublicKey: {
|
||||||
|
id publicKey = (__bridge_transfer id)SecTrustCopyPublicKey(serverTrust);
|
||||||
|
|
||||||
|
if ([[self.class pinnedPublicKeys] containsObject:publicKey]) {
|
||||||
|
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
||||||
|
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
||||||
|
} else {
|
||||||
|
[[challenge sender] cancelAuthenticationChallenge:challenge];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AFSSLPinningModeCertificate: {
|
||||||
|
SecCertificateRef serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
|
||||||
|
NSData *serverCertificateData = (__bridge_transfer NSData *)SecCertificateCopyData(serverCertificate);
|
||||||
|
|
||||||
|
if ([[[self class] pinnedCertificates] containsObject:serverCertificateData]) {
|
||||||
|
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
||||||
|
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
||||||
|
} else {
|
||||||
|
[[challenge sender] cancelAuthenticationChallenge:challenge];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AFSSLPinningModeNone: {
|
||||||
|
#ifdef _AFNETWORKING_ALLOW_INVALID_SSL_CERTIFICATES_
|
||||||
|
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
||||||
|
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
||||||
|
#else
|
||||||
|
SecTrustResultType result = 0;
|
||||||
|
OSStatus status = SecTrustEvaluate(serverTrust, &result);
|
||||||
|
NSAssert(status == noErr, @"SecTrustEvaluate error: %ld", (long int)status);
|
||||||
|
|
||||||
|
if (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed) {
|
||||||
|
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
|
||||||
|
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
|
||||||
|
} else {
|
||||||
|
[[challenge sender] cancelAuthenticationChallenge:challenge];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
- (BOOL)connection:(NSURLConnection *)connection
|
- (BOOL)connection:(NSURLConnection *)connection
|
||||||
canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
|
canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
|
||||||
{
|
{
|
||||||
|
|
@ -631,18 +713,18 @@ didReceiveResponse:(NSURLResponse *)response
|
||||||
- (void)connection:(NSURLConnection __unused *)connection
|
- (void)connection:(NSURLConnection __unused *)connection
|
||||||
didReceiveData:(NSData *)data
|
didReceiveData:(NSData *)data
|
||||||
{
|
{
|
||||||
self.totalBytesRead += [data length];
|
|
||||||
|
|
||||||
if ([self.outputStream hasSpaceAvailable]) {
|
if ([self.outputStream hasSpaceAvailable]) {
|
||||||
const uint8_t *dataBuffer = (uint8_t *) [data bytes];
|
const uint8_t *dataBuffer = (uint8_t *) [data bytes];
|
||||||
[self.outputStream write:&dataBuffer[0] maxLength:[data length]];
|
[self.outputStream write:&dataBuffer[0] maxLength:[data length]];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.downloadProgress) {
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
self.totalBytesRead += [data length];
|
||||||
|
|
||||||
|
if (self.downloadProgress) {
|
||||||
self.downloadProgress([data length], self.totalBytesRead, self.response.expectedContentLength);
|
self.downloadProgress([data length], self.totalBytesRead, self.response.expectedContentLength);
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)connectionDidFinishLoading:(NSURLConnection __unused *)connection {
|
- (void)connectionDidFinishLoading:(NSURLConnection __unused *)connection {
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,12 @@
|
||||||
|
|
||||||
#include <Availability.h>
|
#include <Availability.h>
|
||||||
|
|
||||||
static dispatch_queue_t af_xml_request_operation_processing_queue;
|
|
||||||
static dispatch_queue_t xml_request_operation_processing_queue() {
|
static dispatch_queue_t xml_request_operation_processing_queue() {
|
||||||
if (af_xml_request_operation_processing_queue == NULL) {
|
static dispatch_queue_t af_xml_request_operation_processing_queue;
|
||||||
af_xml_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.xml-request.processing", 0);
|
static dispatch_once_t onceToken;
|
||||||
}
|
dispatch_once(&onceToken, ^{
|
||||||
|
af_xml_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.xml-request.processing", DISPATCH_QUEUE_CONCURRENT);
|
||||||
|
});
|
||||||
|
|
||||||
return af_xml_request_operation_processing_queue;
|
return af_xml_request_operation_processing_queue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,6 @@ static char kAFImageRequestOperationObjectKey;
|
||||||
placeholderImage:(UIImage *)placeholderImage
|
placeholderImage:(UIImage *)placeholderImage
|
||||||
{
|
{
|
||||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
|
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
|
||||||
[request setHTTPShouldHandleCookies:NO];
|
|
||||||
[request addValue:@"image/*" forHTTPHeaderField:@"Accept"];
|
[request addValue:@"image/*" forHTTPHeaderField:@"Accept"];
|
||||||
|
|
||||||
[self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil failure:nil];
|
[self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil failure:nil];
|
||||||
|
|
@ -102,21 +101,22 @@ static char kAFImageRequestOperationObjectKey;
|
||||||
|
|
||||||
UIImage *cachedImage = [[[self class] af_sharedImageCache] cachedImageForRequest:urlRequest];
|
UIImage *cachedImage = [[[self class] af_sharedImageCache] cachedImageForRequest:urlRequest];
|
||||||
if (cachedImage) {
|
if (cachedImage) {
|
||||||
self.image = cachedImage;
|
|
||||||
self.af_imageRequestOperation = nil;
|
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
success(nil, nil, cachedImage);
|
success(nil, nil, cachedImage);
|
||||||
|
} else {
|
||||||
|
self.image = cachedImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.af_imageRequestOperation = nil;
|
||||||
} else {
|
} else {
|
||||||
self.image = placeholderImage;
|
self.image = placeholderImage;
|
||||||
|
|
||||||
AFImageRequestOperation *requestOperation = [[AFImageRequestOperation alloc] initWithRequest:urlRequest];
|
AFImageRequestOperation *requestOperation = [[AFImageRequestOperation alloc] initWithRequest:urlRequest];
|
||||||
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
|
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
|
||||||
if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) {
|
if ([urlRequest isEqual:[self.af_imageRequestOperation request]]) {
|
||||||
if (success) {
|
if (success) {
|
||||||
success(operation.request, operation.response, responseObject);
|
success(operation.request, operation.response, responseObject);
|
||||||
} else {
|
} else if (responseObject) {
|
||||||
self.image = responseObject;
|
self.image = responseObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +127,7 @@ static char kAFImageRequestOperationObjectKey;
|
||||||
|
|
||||||
[[[self class] af_sharedImageCache] cacheImage:responseObject forRequest:urlRequest];
|
[[[self class] af_sharedImageCache] cacheImage:responseObject forRequest:urlRequest];
|
||||||
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
|
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
|
||||||
if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) {
|
if ([urlRequest isEqual:[self.af_imageRequestOperation request]]) {
|
||||||
if (failure) {
|
if (failure) {
|
||||||
failure(operation.request, operation.response, error);
|
failure(operation.request, operation.response, error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
312
CHANGES
312
CHANGES
|
|
@ -1,67 +1,195 @@
|
||||||
|
= 1.2.0 (2013-03-24)
|
||||||
|
|
||||||
|
* Add `SSLPinningMode` property to `AFHTTPClient` (Oliver Letterer, Kevin
|
||||||
|
Harwood, Adam Becevello, Dustin Barker, Mattt Thompson)
|
||||||
|
|
||||||
|
* Add single quote ("'"), comma (","), and asterix ("*") to escaped URL
|
||||||
|
encoding characters (Eric Florenzano, Marc Nijdam, Garrett Murray)
|
||||||
|
|
||||||
|
* Add `credential` property to `AFURLConnectionOperation` (Mattt Thompson)
|
||||||
|
|
||||||
|
* Add `-setDefaultCredential:` to `AFHTTPClient`
|
||||||
|
|
||||||
|
* Add `shouldUseCredentialStorage` property to `AFURLConnectionOperation`
|
||||||
|
(Mattt Thompson)
|
||||||
|
|
||||||
|
* Add support for repeated key value pairs in `AFHTTPClient` URL query string
|
||||||
|
(Nick Dawson)
|
||||||
|
|
||||||
|
* Add `AFMultipartFormData -
|
||||||
|
appendPartWithFileURL:name:fileName:mimeType:error` (Daniel Rodríguez Troitiño)
|
||||||
|
|
||||||
|
* Add `AFMultipartFormData -
|
||||||
|
appendPartWithInputStream:name:fileName:mimeType:` (@joein3d)
|
||||||
|
|
||||||
|
* Change SSL pinning to be runtime property on `AFURLConnectionOperation`
|
||||||
|
rather than defined by macro (Oliver Letterer)
|
||||||
|
|
||||||
|
* Change `AFMultipartBodyStream` to `AFMultipartBodyStreamProvider`, vending
|
||||||
|
one side of a bound CFStream pair rather than subclassing `NSInputStream` (Mike
|
||||||
|
Ash)
|
||||||
|
|
||||||
|
* Change default `Accept-Language` header in `AFHTTPClient` (@therigu, Mattt
|
||||||
|
Thompson)
|
||||||
|
|
||||||
|
* Change `AFHTTPClient` operation cancellation to be based on request URL path
|
||||||
|
rather than absolute URL string (Mattt Thompson)
|
||||||
|
|
||||||
|
* Change request operation subclass processing queues to use
|
||||||
|
`DISPATCH_QUEUE_CONCURRENT` (Mattt Thompson)
|
||||||
|
|
||||||
|
* Change `UIImageView+AFNetworking` to resolve asymmetry in cached image case
|
||||||
|
between success block provided and not provided (@Eveets, Mattt Thompson)
|
||||||
|
|
||||||
|
* Change `UIImageView+AFNetworking` to compare `NSURLRequest` instead of
|
||||||
|
`NSURL` to determine if previous request was equivalent (Cédric Luthi)
|
||||||
|
|
||||||
|
* Change `UIImageView+AFNetworking` to only set image if non-`nil` (Sean
|
||||||
|
Kovacs)
|
||||||
|
|
||||||
|
* Change indentation settings to four spaces at the project level (Cédric
|
||||||
|
Luthi)
|
||||||
|
|
||||||
|
* Change `AFNetworkActivityIndicatorManager` to only update if requests have a
|
||||||
|
non-`nil` URL (Cédric Luthi)
|
||||||
|
|
||||||
|
* Change `UIImageView+AFNetworking` to not do `setHTTPShouldHandleCookies`
|
||||||
|
(Konstantinos Vaggelakos)
|
||||||
|
|
||||||
|
* Fix request stream exhaustion error on authentication challenges (Alex
|
||||||
|
Burgel)
|
||||||
|
|
||||||
|
* Fix implementation to use `NSURL` methods instead of `CFURL` functions where
|
||||||
|
applicable (Cédric Luthi)
|
||||||
|
|
||||||
|
* Fix race condition in `UIImageView+AFNetworking` (Peyman)
|
||||||
|
|
||||||
|
* Fix `responseJSON`, `responseString`, and `responseStringEncoding` to be
|
||||||
|
threadsafe (Jon Parise, Mattt Thompson)
|
||||||
|
|
||||||
|
* Fix `AFContentTypeForPathExtension` to ensure non-`NULL` content return
|
||||||
|
value (Zach Waugh)
|
||||||
|
|
||||||
|
* Fix documentation for `appendPartWithFileURL:name:error:`
|
||||||
|
(Daniel Rodríguez Troitiño)
|
||||||
|
|
||||||
|
* Fix request operation subclass processing queues to initialize with
|
||||||
|
`dispatch_once` (Sasmito Adibowo)
|
||||||
|
|
||||||
|
* Fix posting of `AFNetworkingOperationDidStartNotification` and
|
||||||
|
`AFNetworkingOperationDidFinishNotification` to avoid crashes when logging in
|
||||||
|
response to notifications (Blake Watters)
|
||||||
|
|
||||||
|
* Fix ordering of registered operation consultation in `AFHTTPClient` (Joel
|
||||||
|
Parsons)
|
||||||
|
|
||||||
|
* Fix warning: multiple methods named 'postNotificationName:object:' found
|
||||||
|
[-Wstrict-selector-match] (Oliver Jones)
|
||||||
|
|
||||||
|
* Fix warning: multiple methods named 'objectForKey:' found
|
||||||
|
[-Wstrict-selector-match] (Oliver Jones)
|
||||||
|
|
||||||
|
* Fix warning: weak receiver may be unpredictably set to nil
|
||||||
|
[-Wreceiver-is-weak] (Oliver Jones)
|
||||||
|
|
||||||
|
* Fix missing #pragma clang diagnostic pop (Steven Fisher)
|
||||||
|
|
||||||
= 1.1.0 (2012-12-27)
|
= 1.1.0 (2012-12-27)
|
||||||
|
|
||||||
* Add optional SSL certificate pinning with `#define _AFNETWORKING_PIN_SSL_CERTIFICATES_` (Dustin Barker)
|
* Add optional SSL certificate pinning with `#define
|
||||||
|
_AFNETWORKING_PIN_SSL_CERTIFICATES_` (Dustin Barker)
|
||||||
|
|
||||||
* Add `responseStringEncoding` property to `AFURLConnectionOperation` (Mattt Thompson)
|
* Add `responseStringEncoding` property to `AFURLConnectionOperation` (Mattt
|
||||||
|
Thompson)
|
||||||
|
|
||||||
* Add `userInfo` property to `AFURLConnectionOperation` (Mattt Thompson, Steven Fisher)
|
* Add `userInfo` property to `AFURLConnectionOperation` (Mattt Thompson,
|
||||||
|
Steven Fisher)
|
||||||
|
|
||||||
* Change behavior to cause a failure when an operation is cancelled (Daniel Tull)
|
* Change behavior to cause a failure when an operation is cancelled (Daniel
|
||||||
|
Tull)
|
||||||
|
|
||||||
* Change return type of class constructors to `instancetype` (@guykogus)
|
* Change return type of class constructors to `instancetype` (@guykogus)
|
||||||
|
|
||||||
* Change notifications to always being posted on an asynchronously-dispatched block run on the main queue (Evadne Wu, Mattt Thompson)
|
* Change notifications to always being posted on an asynchronously-dispatched
|
||||||
|
block run on the main queue (Evadne Wu, Mattt Thompson)
|
||||||
|
|
||||||
* Change from NSLocalizedString to NSLocalizedStringFromTable with AFNetworking.strings table for localized strings (Cédric Luthi)
|
* Change from NSLocalizedString to NSLocalizedStringFromTable with
|
||||||
|
AFNetworking.strings table for localized strings (Cédric Luthi)
|
||||||
|
|
||||||
* Change `-appendPartWithHeaders:body:` to add assertion handler for existence of body data parameter (Jonathan Beilin)
|
* Change `-appendPartWithHeaders:body:` to add assertion handler for existence
|
||||||
|
of body data parameter (Jonathan Beilin)
|
||||||
|
|
||||||
* Change `AFHTTPRequestOperation -responseString` to follow guidelines from RFC 2616 regarding the use of string encoding when none is specified in the response (Jorge Bernal)
|
* Change `AFHTTPRequestOperation -responseString` to follow guidelines from
|
||||||
|
RFC 2616 regarding the use of string encoding when none is specified in the
|
||||||
|
response (Jorge Bernal)
|
||||||
|
|
||||||
* Change AFHTTPClient parameter serialization dictionary keys with `caseInsensitiveCompare:` to ensure
|
* Change AFHTTPClient parameter serialization dictionary keys with
|
||||||
deterministic ordering of query string parameters, which may otherwise
|
`caseInsensitiveCompare:` to ensure
|
||||||
cause ambiguous representations of nested parameters (James Coleman,
|
deterministic ordering of query string parameters, which may otherwise
|
||||||
|
cause ambiguous representations of nested parameters (James Coleman,
|
||||||
Mattt Thompson)
|
Mattt Thompson)
|
||||||
|
|
||||||
* Fix -Wstrict-selector-match warnings raised by Xcode 4.6DP3 (Jesse Collis, Cédric Luthi)
|
* Fix -Wstrict-selector-match warnings raised by Xcode 4.6DP3 (Jesse Collis,
|
||||||
|
Cédric Luthi)
|
||||||
|
|
||||||
* Fix NSJSONSerialization crash with Unicode character escapes in JSON response (Mathijs Kadijk)
|
* Fix NSJSONSerialization crash with Unicode character escapes in JSON
|
||||||
|
response (Mathijs Kadijk)
|
||||||
|
|
||||||
* Fix issue with early return in -startMonitoringNetworkReachability if network reachability object could not be created (i.e. invalid hostnames) (Basil Shkara)
|
* Fix issue with early return in -startMonitoringNetworkReachability if
|
||||||
|
network reachability object could not be created (i.e. invalid hostnames)
|
||||||
|
(Basil Shkara)
|
||||||
|
|
||||||
* Fix retain cycles in AFImageRequestOperation.m and AFHTTPClient.m caused by strong references within blocks (Nick Forge)
|
* Fix retain cycles in AFImageRequestOperation.m and AFHTTPClient.m caused by
|
||||||
|
strong references within blocks (Nick Forge)
|
||||||
|
|
||||||
* Fix issue caused by Rails behavior of returning a single space in head :ok responses, which is interpreted as invalid (Sebastian Ludwig)
|
* Fix issue caused by Rails behavior of returning a single space in head :ok
|
||||||
|
responses, which is interpreted as invalid (Sebastian Ludwig)
|
||||||
|
|
||||||
* Fix issue in streaming multipart upload, where final encapsulation boundary would not be appended if it was larger than the available buffer, causing a potential timeout (Tomohisa Takaoka, David Kasper)
|
* Fix issue in streaming multipart upload, where final encapsulation boundary
|
||||||
|
would not be appended if it was larger than the available buffer, causing a
|
||||||
|
potential timeout (Tomohisa Takaoka, David Kasper)
|
||||||
|
|
||||||
* Fix memory leak of network reachability callback block (Mattt Thompson)
|
* Fix memory leak of network reachability callback block (Mattt Thompson)
|
||||||
|
|
||||||
* Fix `-initWithCoder:` for `AFURLConnectionOperation` and `AFHTTPClient` to cast scalar types (Mattt Thompson)
|
* Fix `-initWithCoder:` for `AFURLConnectionOperation` and `AFHTTPClient` to
|
||||||
|
cast scalar types (Mattt Thompson)
|
||||||
|
|
||||||
* Fix bug in `-enqueueBatchOfHTTPRequestOperations:...` to by using `addOperations:waitUntilFinished:` instead of adding each operation individually. (Mattt Thompson)
|
* Fix bug in `-enqueueBatchOfHTTPRequestOperations:...` to by using
|
||||||
|
`addOperations:waitUntilFinished:` instead of adding each operation
|
||||||
|
individually. (Mattt Thompson)
|
||||||
|
|
||||||
* Change `#warning` messages of checks for `CoreServices` and `MobileCoreServices` to message according to the build target platform (Mattt Thompson)
|
* Change `#warning` messages of checks for `CoreServices` and
|
||||||
|
`MobileCoreServices` to message according to the build target platform (Mattt
|
||||||
|
Thompson)
|
||||||
|
|
||||||
* Change `AFQueryStringFromParametersWithEncoding` to create keys string representations using the description method as specified in documentation (Cédric Luthi)
|
* Change `AFQueryStringFromParametersWithEncoding` to create keys string
|
||||||
|
representations using the description method as specified in documentation
|
||||||
|
(Cédric Luthi)
|
||||||
|
|
||||||
* Fix __unused keywords for better Xcode indexing (Christian Rasmussen)
|
* Fix __unused keywords for better Xcode indexing (Christian Rasmussen)
|
||||||
|
|
||||||
* Fix warning: unused parameter 'x' [-Werror,-Wunused-parameter] (Oliver Jones)
|
* Fix warning: unused parameter 'x' [-Werror,-Wunused-parameter] (Oliver Jones)
|
||||||
|
|
||||||
* Fix warning: property is assumed atomic by default [-Werror,-Wimplicit-atomic-properties] (Oliver Jones)
|
* Fix warning: property is assumed atomic by default
|
||||||
|
[-Werror,-Wimplicit-atomic-properties] (Oliver Jones)
|
||||||
* Fix warning: weak receiver may be unpredictably null in ARC mode [-Werror,-Wreceiver-is-weak] (Oliver Jones)
|
|
||||||
|
* Fix warning: weak receiver may be unpredictably null in ARC mode
|
||||||
* Fix warning: multiple methods named 'selector' found [-Werror,-Wstrict-selector-match] (Oliver Jones)
|
[-Werror,-Wreceiver-is-weak] (Oliver Jones)
|
||||||
|
|
||||||
|
* Fix warning: multiple methods named 'selector' found
|
||||||
|
[-Werror,-Wstrict-selector-match] (Oliver Jones)
|
||||||
|
|
||||||
* Fix warning: 'macro' is not defined, evaluates to 0 (Oliver Jones)
|
* Fix warning: 'macro' is not defined, evaluates to 0 (Oliver Jones)
|
||||||
|
|
||||||
* Fix warning: atomic by default property 'X' has a user (Oliver Jones)defined getter (property should be marked 'atomic' if this is intended) [-Werror, -Wcustom-atomic-properties] (Oliver Jones)
|
* Fix warning: atomic by default property 'X' has a user (Oliver Jones)defined
|
||||||
|
getter (property should be marked 'atomic' if this is intended) [-Werror,
|
||||||
* Fix warning: 'response' was marked unused but was used [-Werror,-Wused-but-marked-unused] (Oliver Jones)
|
-Wcustom-atomic-properties] (Oliver Jones)
|
||||||
|
|
||||||
* Fix warning: enumeration value 'AFFinalBoundaryPhase' not explicitly handled in switch [-Werror,-Wswitch-enum] (Oliver Jones)
|
* Fix warning: 'response' was marked unused but was used
|
||||||
|
[-Werror,-Wused-but-marked-unused] (Oliver Jones)
|
||||||
|
|
||||||
|
* Fix warning: enumeration value 'AFFinalBoundaryPhase' not explicitly handled
|
||||||
|
in switch [-Werror,-Wswitch-enum] (Oliver Jones)
|
||||||
|
|
||||||
= 1.0.1 / 2012-11-01
|
= 1.0.1 / 2012-11-01
|
||||||
|
|
||||||
|
|
@ -72,7 +200,7 @@ was not correctly calculated (Stan Chang Khin Boon)
|
||||||
placeholderImage:success:failure`:, it is now the responsibility of the
|
placeholderImage:success:failure`:, it is now the responsibility of the
|
||||||
block to set the image of the image view (Mattt Thompson)
|
block to set the image of the image view (Mattt Thompson)
|
||||||
|
|
||||||
* Add `JSONReadingOptions` property to `AFJSONRequestOperation` (Jeremy
|
* Add `JSONReadingOptions` property to `AFJSONRequestOperation` (Jeremy
|
||||||
Foo, Mattt Thompson)
|
Foo, Mattt Thompson)
|
||||||
|
|
||||||
* Using __weak self / __strong self pattern to break retain cycles in
|
* Using __weak self / __strong self pattern to break retain cycles in
|
||||||
|
|
@ -80,10 +208,10 @@ block to set the image of the image view (Mattt Thompson)
|
||||||
|
|
||||||
* Fix parameter encoding to leave period (`.`) unescaped (Diego Torres)
|
* Fix parameter encoding to leave period (`.`) unescaped (Diego Torres)
|
||||||
|
|
||||||
* Fixing last file component in multipart form part creation (Sylver
|
* Fixing last file component in multipart form part creation (Sylver
|
||||||
Bruneau)
|
Bruneau)
|
||||||
|
|
||||||
* Remove executable permission on AFHTTPClient source files (Andrew
|
* Remove executable permission on AFHTTPClient source files (Andrew
|
||||||
Sardone)
|
Sardone)
|
||||||
|
|
||||||
* Fix warning (error with -Werror) on implicit 64 to 32 conversion (Dan
|
* Fix warning (error with -Werror) on implicit 64 to 32 conversion (Dan
|
||||||
|
|
@ -96,144 +224,144 @@ block to set the image of the image view (Mattt Thompson)
|
||||||
= 1.0 / 2012-10-15
|
= 1.0 / 2012-10-15
|
||||||
|
|
||||||
* AFNetworking now requires iOS 5 / Mac OSX 10.7 or higher (Mattt Thompson)
|
* AFNetworking now requires iOS 5 / Mac OSX 10.7 or higher (Mattt Thompson)
|
||||||
|
|
||||||
* AFNetworking now uses Automatic Reference Counting (ARC) (Mattt Thompson)
|
* AFNetworking now uses Automatic Reference Counting (ARC) (Mattt Thompson)
|
||||||
|
|
||||||
* AFNetworking raises compiler warnings for missing features when
|
* AFNetworking raises compiler warnings for missing features when
|
||||||
SystemConfiguration or CoreServices / MobileCoreServices frameworks are not
|
SystemConfiguration or CoreServices / MobileCoreServices frameworks are not
|
||||||
included in the project and imported in the precompiled headers (Mattt
|
included in the project and imported in the precompiled headers (Mattt
|
||||||
Thompson)
|
Thompson)
|
||||||
|
|
||||||
* AFNetworking now raises compiler error when not compiled with ARC (Steven
|
* AFNetworking now raises compiler error when not compiled with ARC (Steven
|
||||||
Fisher)
|
Fisher)
|
||||||
|
|
||||||
* Add `NSCoding` and `NSCopying` protocol conformance to
|
* Add `NSCoding` and `NSCopying` protocol conformance to
|
||||||
`AFURLConnectionOperation` and `AFHTTPClient` (Mattt Thompson)
|
`AFURLConnectionOperation` and `AFHTTPClient` (Mattt Thompson)
|
||||||
|
|
||||||
* Add substantial improvements HTTP multipart streaming support, having
|
* Add substantial improvements HTTP multipart streaming support, having
|
||||||
files streamed directly from disk and read sequentially from a custom input
|
files streamed directly from disk and read sequentially from a custom input
|
||||||
stream (Max Lansing, Stan Chang Khin Boon, Mattt Thompson)
|
stream (Max Lansing, Stan Chang Khin Boon, Mattt Thompson)
|
||||||
|
|
||||||
* Add `AFMultipartFormData -throttleBandwidthWithPacketSize:delay:` as
|
* Add `AFMultipartFormData -throttleBandwidthWithPacketSize:delay:` as
|
||||||
workaround to issues when uploading over 3G (Mattt Thompson)
|
workaround to issues when uploading over 3G (Mattt Thompson)
|
||||||
|
|
||||||
* Add request and response to `userInfo` of errors returned from failing
|
* Add request and response to `userInfo` of errors returned from failing
|
||||||
`AFHTTPRequestOperation` (Mattt Thompson)
|
`AFHTTPRequestOperation` (Mattt Thompson)
|
||||||
|
|
||||||
* Add `userInfo` dictionary with current status in reachability changes
|
* Add `userInfo` dictionary with current status in reachability changes
|
||||||
(Mattt Thompson)
|
(Mattt Thompson)
|
||||||
|
|
||||||
* Add `Accept` header for image requests in `UIImageView` category (Bratley
|
* Add `Accept` header for image requests in `UIImageView` category (Bratley
|
||||||
Lower)
|
Lower)
|
||||||
|
|
||||||
* Add explicit declaration of `NSURLConnection` delegate methods so that
|
* Add explicit declaration of `NSURLConnection` delegate methods so that
|
||||||
they can be overridden in subclasses (Mattt Thompson, Evan Grim)
|
they can be overridden in subclasses (Mattt Thompson, Evan Grim)
|
||||||
|
|
||||||
* Add parameter validation to match conditions specified in documentation
|
* Add parameter validation to match conditions specified in documentation
|
||||||
(Jason Brennan, Mattt Thompson)
|
(Jason Brennan, Mattt Thompson)
|
||||||
|
|
||||||
* Add import to `UIKit` to avoid build errors from `UIDevice` references in
|
* Add import to `UIKit` to avoid build errors from `UIDevice` references in
|
||||||
`User-Agent` default header (Blake Watters)
|
`User-Agent` default header (Blake Watters)
|
||||||
|
|
||||||
* Remove `AFJSONUtilities` in favor of `NSJSONSerialization` (Mattt Thompson)
|
* Remove `AFJSONUtilities` in favor of `NSJSONSerialization` (Mattt Thompson)
|
||||||
|
|
||||||
* Remove `extern` declaration of `AFURLEncodedStringFromStringWithEncoding`
|
* Remove `extern` declaration of `AFURLEncodedStringFromStringWithEncoding`
|
||||||
function (`CFURLCreateStringByAddingPercentEscapes` should be used instead)
|
function (`CFURLCreateStringByAddingPercentEscapes` should be used instead)
|
||||||
(Mattt Thompson)
|
(Mattt Thompson)
|
||||||
|
|
||||||
* Remove `setHTTPShouldHandleCookies:NO` from `AFHTTPClient` (@phamsonha,
|
* Remove `setHTTPShouldHandleCookies:NO` from `AFHTTPClient` (@phamsonha,
|
||||||
Mattt Thompson)
|
Mattt Thompson)
|
||||||
|
|
||||||
* Remove `dispatch_retain` / `dispatch_release` with ARC in iOS 6 (Benoit
|
* Remove `dispatch_retain` / `dispatch_release` with ARC in iOS 6 (Benoit
|
||||||
Bourdon)
|
Bourdon)
|
||||||
|
|
||||||
* Fix threading issue with `AFNetworkActivityIndicatorManager` (Eric Patey)
|
* Fix threading issue with `AFNetworkActivityIndicatorManager` (Eric Patey)
|
||||||
|
|
||||||
* Fix issue where `AFNetworkActivityIndicatorManager` count could become
|
* Fix issue where `AFNetworkActivityIndicatorManager` count could become
|
||||||
negative (@ap4y)
|
negative (@ap4y)
|
||||||
|
|
||||||
* Fix properties to explicitly set options to suppress warnings (Wen-Hao
|
* Fix properties to explicitly set options to suppress warnings (Wen-Hao
|
||||||
Lue, Mattt Thompson)
|
Lue, Mattt Thompson)
|
||||||
|
|
||||||
* Fix compiler warning caused by mismatched types in upload / download
|
* Fix compiler warning caused by mismatched types in upload / download
|
||||||
progress blocks (Gareth du Plooy, tomas.a)
|
progress blocks (Gareth du Plooy, tomas.a)
|
||||||
|
|
||||||
* Fix weak / strong variable relationships in `completionBlock` (Peter
|
* Fix weak / strong variable relationships in `completionBlock` (Peter
|
||||||
Steinberger)
|
Steinberger)
|
||||||
|
|
||||||
* Fix string formatting syntax warnings caused by type mismatch (David
|
* Fix string formatting syntax warnings caused by type mismatch (David
|
||||||
Keegan, Steven Fisher, George Cox)
|
Keegan, Steven Fisher, George Cox)
|
||||||
|
|
||||||
* Fix minor potential security vulnerability by explicitly using string
|
* Fix minor potential security vulnerability by explicitly using string
|
||||||
format in NSError localizedDescription value in userInfo (Steven Fisher)
|
format in NSError localizedDescription value in userInfo (Steven Fisher)
|
||||||
|
|
||||||
* Fix `AFURLConnectionOperation -pause` by adding state checks to prevent
|
* Fix `AFURLConnectionOperation -pause` by adding state checks to prevent
|
||||||
likely memory issues when resuming (Mattt Thompson)
|
likely memory issues when resuming (Mattt Thompson)
|
||||||
|
|
||||||
* Fix warning caused by miscast of type when
|
* Fix warning caused by miscast of type when
|
||||||
`CLANG_WARN_IMPLICIT_SIGN_CONVERSION` is set (Steven Fisher)
|
`CLANG_WARN_IMPLICIT_SIGN_CONVERSION` is set (Steven Fisher)
|
||||||
|
|
||||||
* Fix incomplete implementation warning in example code (Steven Fisher)
|
* Fix incomplete implementation warning in example code (Steven Fisher)
|
||||||
|
|
||||||
* Fix warning caused by using `==` comparator on floats (Steven Fisher)
|
* Fix warning caused by using `==` comparator on floats (Steven Fisher)
|
||||||
|
|
||||||
* Fix iOS 4 bug where file URLs return `NSURLResponse` rather than
|
* Fix iOS 4 bug where file URLs return `NSURLResponse` rather than
|
||||||
`NSHTTPURLResponse` objects (Leo Lobato)
|
`NSHTTPURLResponse` objects (Leo Lobato)
|
||||||
|
|
||||||
* Fix calculation of finished operations in batch operation progress
|
* Fix calculation of finished operations in batch operation progress
|
||||||
callback (Mattt Thompson)
|
callback (Mattt Thompson)
|
||||||
|
|
||||||
* Fix documentation typos (Steven Fisher, Matthias Wessendorf,
|
* Fix documentation typos (Steven Fisher, Matthias Wessendorf,
|
||||||
jorge@miv.uk.com)
|
jorge@miv.uk.com)
|
||||||
|
|
||||||
* Fix `hasAcceptableStatusCode` to return true after a network failure (Tony
|
* Fix `hasAcceptableStatusCode` to return true after a network failure (Tony
|
||||||
Million)
|
Million)
|
||||||
|
|
||||||
* Fix warning about missing prototype for private static method (Stephan
|
* Fix warning about missing prototype for private static method (Stephan
|
||||||
Diederich)
|
Diederich)
|
||||||
|
|
||||||
* Fix issue where `nil` content type resulted in unacceptable content type
|
* Fix issue where `nil` content type resulted in unacceptable content type
|
||||||
(Mattt Thompson)
|
(Mattt Thompson)
|
||||||
|
|
||||||
* Fix bug related to setup and scheduling of output stream (Stephen Tramer)
|
* Fix bug related to setup and scheduling of output stream (Stephen Tramer)
|
||||||
|
|
||||||
* Fix AFContentTypesFromHTTPHeader to correctly handle comma-delimited
|
* Fix AFContentTypesFromHTTPHeader to correctly handle comma-delimited
|
||||||
content types (Peyman, Mattt Thompson, @jsm174)
|
content types (Peyman, Mattt Thompson, @jsm174)
|
||||||
|
|
||||||
* Fix crash caused by `_networkReachability` not being set to `NULL` after
|
* Fix crash caused by `_networkReachability` not being set to `NULL` after
|
||||||
releasing (Blake Watters)
|
releasing (Blake Watters)
|
||||||
|
|
||||||
* Fix Podspec to correctly import required headers and use ARC (Eloy Durán,
|
* Fix Podspec to correctly import required headers and use ARC (Eloy Durán,
|
||||||
Blake Watters)
|
Blake Watters)
|
||||||
|
|
||||||
* Fix query string parameter escaping to leave square brackets unescaped
|
* Fix query string parameter escaping to leave square brackets unescaped
|
||||||
(Mattt Thompson)
|
(Mattt Thompson)
|
||||||
|
|
||||||
* Fix query string parameter encoding of `NSNull` values (Daniel Rinser)
|
* Fix query string parameter encoding of `NSNull` values (Daniel Rinser)
|
||||||
|
|
||||||
* Fix error caused by referencing `__IPHONE_OS_VERSION_MIN_REQUIRED` without
|
* Fix error caused by referencing `__IPHONE_OS_VERSION_MIN_REQUIRED` without
|
||||||
importing `Availability.h` (Blake Watters)
|
importing `Availability.h` (Blake Watters)
|
||||||
|
|
||||||
* Update example to use App.net API, as Twitter shut off its unauthorized
|
* Update example to use App.net API, as Twitter shut off its unauthorized
|
||||||
access to the public timeline (Mattt Thompson)
|
access to the public timeline (Mattt Thompson)
|
||||||
|
|
||||||
* Update `AFURLConnectionOperation` to replace `NSAutoReleasePool` with
|
* Update `AFURLConnectionOperation` to replace `NSAutoReleasePool` with
|
||||||
`@autoreleasepool` (Mattt Thompson)
|
`@autoreleasepool` (Mattt Thompson)
|
||||||
|
|
||||||
* Update `AFHTTPClient` operation queue to specify
|
* Update `AFHTTPClient` operation queue to specify
|
||||||
`NSOperationQueueDefaultMaxConcurrentOperationCount` rather than
|
`NSOperationQueueDefaultMaxConcurrentOperationCount` rather than
|
||||||
previously-defined constant (Mattt Thompson)
|
previously-defined constant (Mattt Thompson)
|
||||||
|
|
||||||
* Update `AFHTTPClient -initWithBaseURL` to automatically append trailing
|
* Update `AFHTTPClient -initWithBaseURL` to automatically append trailing
|
||||||
slash, so as to fix common issue where default path is not respected without
|
slash, so as to fix common issue where default path is not respected without
|
||||||
trailing slash (Steven Fisher)
|
trailing slash (Steven Fisher)
|
||||||
|
|
||||||
* Update default `AFHTTPClient` `User-Agent` header strings (Mattt Thompson,
|
* Update default `AFHTTPClient` `User-Agent` header strings (Mattt Thompson,
|
||||||
Steven Fisher)
|
Steven Fisher)
|
||||||
|
|
||||||
* Update icons for iOS example application (Mattt Thompson)
|
* Update icons for iOS example application (Mattt Thompson)
|
||||||
|
|
||||||
* Update `numberOfCompletedOperations` variable in progress block to be
|
* Update `numberOfCompletedOperations` variable in progress block to be
|
||||||
renamed to `numberOfFinishedOperations` (Mattt Thompson)
|
renamed to `numberOfFinishedOperations` (Mattt Thompson)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
F82EB080159A172000B10B56 /* AFPropertyListRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB077159A172000B10B56 /* AFPropertyListRequestOperation.m */; };
|
F82EB080159A172000B10B56 /* AFPropertyListRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB077159A172000B10B56 /* AFPropertyListRequestOperation.m */; };
|
||||||
F82EB081159A172000B10B56 /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB079159A172000B10B56 /* AFURLConnectionOperation.m */; };
|
F82EB081159A172000B10B56 /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB079159A172000B10B56 /* AFURLConnectionOperation.m */; };
|
||||||
F82EB082159A172000B10B56 /* AFXMLRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB07B159A172000B10B56 /* AFXMLRequestOperation.m */; };
|
F82EB082159A172000B10B56 /* AFXMLRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F82EB07B159A172000B10B56 /* AFXMLRequestOperation.m */; };
|
||||||
|
F88812F216C533E9003C8B8C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F88812F116C533E9003C8B8C /* Security.framework */; };
|
||||||
F8A847CF161F55A500940F39 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8A847CE161F55A500940F39 /* CoreServices.framework */; };
|
F8A847CF161F55A500940F39 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8A847CE161F55A500940F39 /* CoreServices.framework */; };
|
||||||
F8A847D2161F55AC00940F39 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */; };
|
F8A847D2161F55AC00940F39 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
@ -57,6 +58,7 @@
|
||||||
F82EB07A159A172000B10B56 /* AFXMLRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFXMLRequestOperation.h; path = ../AFNetworking/AFXMLRequestOperation.h; sourceTree = "<group>"; };
|
F82EB07A159A172000B10B56 /* AFXMLRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFXMLRequestOperation.h; path = ../AFNetworking/AFXMLRequestOperation.h; sourceTree = "<group>"; };
|
||||||
F82EB07B159A172000B10B56 /* AFXMLRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFXMLRequestOperation.m; path = ../AFNetworking/AFXMLRequestOperation.m; sourceTree = "<group>"; };
|
F82EB07B159A172000B10B56 /* AFXMLRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFXMLRequestOperation.m; path = ../AFNetworking/AFXMLRequestOperation.m; sourceTree = "<group>"; };
|
||||||
F877018B159A1CE700B45C0D /* AFNetworking Example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "AFNetworking Example.entitlements"; sourceTree = "<group>"; };
|
F877018B159A1CE700B45C0D /* AFNetworking Example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "AFNetworking Example.entitlements"; sourceTree = "<group>"; };
|
||||||
|
F88812F116C533E9003C8B8C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
||||||
F8A847CE161F55A500940F39 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
|
F8A847CE161F55A500940F39 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
|
||||||
F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
@ -66,6 +68,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
F88812F216C533E9003C8B8C /* Security.framework in Frameworks */,
|
||||||
F8A847D2161F55AC00940F39 /* SystemConfiguration.framework in Frameworks */,
|
F8A847D2161F55AC00940F39 /* SystemConfiguration.framework in Frameworks */,
|
||||||
F8A847CF161F55A500940F39 /* CoreServices.framework in Frameworks */,
|
F8A847CF161F55A500940F39 /* CoreServices.framework in Frameworks */,
|
||||||
F8129C001591061B009BFE23 /* Cocoa.framework in Frameworks */,
|
F8129C001591061B009BFE23 /* Cocoa.framework in Frameworks */,
|
||||||
|
|
@ -78,6 +81,7 @@
|
||||||
F8129BF01591061B009BFE23 = {
|
F8129BF01591061B009BFE23 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
F88812F116C533E9003C8B8C /* Security.framework */,
|
||||||
F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */,
|
F8A847D1161F55AC00940F39 /* SystemConfiguration.framework */,
|
||||||
F8A847CE161F55A500940F39 /* CoreServices.framework */,
|
F8A847CE161F55A500940F39 /* CoreServices.framework */,
|
||||||
F877018B159A1CE700B45C0D /* AFNetworking Example.entitlements */,
|
F877018B159A1CE700B45C0D /* AFNetworking Example.entitlements */,
|
||||||
|
|
@ -86,7 +90,10 @@
|
||||||
F8129BFE1591061B009BFE23 /* Frameworks */,
|
F8129BFE1591061B009BFE23 /* Frameworks */,
|
||||||
F8129BFC1591061B009BFE23 /* Products */,
|
F8129BFC1591061B009BFE23 /* Products */,
|
||||||
);
|
);
|
||||||
|
indentWidth = 4;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
tabWidth = 4;
|
||||||
|
usesTabs = 0;
|
||||||
};
|
};
|
||||||
F8129BFC1591061B009BFE23 /* Products */ = {
|
F8129BFC1591061B009BFE23 /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
|
|
@ -206,7 +213,7 @@
|
||||||
F8129BF21591061B009BFE23 /* Project object */ = {
|
F8129BF21591061B009BFE23 /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0450;
|
LastUpgradeCheck = 0460;
|
||||||
};
|
};
|
||||||
buildConfigurationList = F8129BF51591061B009BFE23 /* Build configuration list for PBXProject "AFNetworking Mac Example" */;
|
buildConfigurationList = F8129BF51591061B009BFE23 /* Build configuration list for PBXProject "AFNetworking Mac Example" */;
|
||||||
compatibilityVersion = "Xcode 3.2";
|
compatibilityVersion = "Xcode 3.2";
|
||||||
|
|
@ -265,6 +272,10 @@
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
|
@ -292,6 +303,10 @@
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = YES;
|
COPY_PHASE_STRIP = YES;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
F8129C7415910C37009BFE23 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F8129C7215910C37009BFE23 /* AppDelegate.m */; };
|
F8129C7415910C37009BFE23 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F8129C7215910C37009BFE23 /* AppDelegate.m */; };
|
||||||
F818101615E6A0C600EF93C2 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50ABD6EC159FC2CE001BE42C /* MobileCoreServices.framework */; };
|
F818101615E6A0C600EF93C2 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50ABD6EC159FC2CE001BE42C /* MobileCoreServices.framework */; };
|
||||||
|
F88812F016C533D6003C8B8C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469E013957DF100DB05C8 /* Security.framework */; };
|
||||||
F8A847C1161F51A300940F39 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C0161F51A300940F39 /* Default-568h@2x.png */; };
|
F8A847C1161F51A300940F39 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C0161F51A300940F39 /* Default-568h@2x.png */; };
|
||||||
F8A847C3161F523E00940F39 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C2161F523E00940F39 /* Default.png */; };
|
F8A847C3161F523E00940F39 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C2161F523E00940F39 /* Default.png */; };
|
||||||
F8A847C5161F524200940F39 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C4161F524200940F39 /* Default@2x.png */; };
|
F8A847C5161F524200940F39 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F8A847C4161F524200940F39 /* Default@2x.png */; };
|
||||||
|
|
@ -95,6 +96,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
F88812F016C533D6003C8B8C /* Security.framework in Frameworks */,
|
||||||
F8E469651395739D00DB05C8 /* UIKit.framework in Frameworks */,
|
F8E469651395739D00DB05C8 /* UIKit.framework in Frameworks */,
|
||||||
F8E469671395739D00DB05C8 /* Foundation.framework in Frameworks */,
|
F8E469671395739D00DB05C8 /* Foundation.framework in Frameworks */,
|
||||||
F8E469691395739D00DB05C8 /* CoreGraphics.framework in Frameworks */,
|
F8E469691395739D00DB05C8 /* CoreGraphics.framework in Frameworks */,
|
||||||
|
|
@ -152,7 +154,10 @@
|
||||||
F8E469631395739D00DB05C8 /* Frameworks */,
|
F8E469631395739D00DB05C8 /* Frameworks */,
|
||||||
F8E469611395739C00DB05C8 /* Products */,
|
F8E469611395739C00DB05C8 /* Products */,
|
||||||
);
|
);
|
||||||
|
indentWidth = 4;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
tabWidth = 4;
|
||||||
|
usesTabs = 0;
|
||||||
};
|
};
|
||||||
F8E469611395739C00DB05C8 /* Products */ = {
|
F8E469611395739C00DB05C8 /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@ extern NSString * const kUserProfileImageDidLoadNotification;
|
||||||
|
|
||||||
@interface User : NSObject
|
@interface User : NSObject
|
||||||
|
|
||||||
@property (readonly) NSUInteger userID;
|
@property (readonly, nonatomic) NSUInteger userID;
|
||||||
@property (readonly) NSString *username;
|
@property (readonly, nonatomic) NSString *username;
|
||||||
@property (unsafe_unretained, readonly) NSURL *avatarImageURL;
|
@property (readonly, nonatomic, unsafe_unretained) NSURL *avatarImageURL;
|
||||||
|
|
||||||
- (id)initWithAttributes:(NSDictionary *)attributes;
|
- (id)initWithAttributes:(NSDictionary *)attributes;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#import <Availability.h>
|
#import <Availability.h>
|
||||||
|
|
||||||
|
#define _AFNETWORKING_PIN_SSL_CERTIFICATES_
|
||||||
|
|
||||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
#ifndef __IPHONE_3_0
|
#ifndef __IPHONE_3_0
|
||||||
#warning "This project uses features only available in iPhone SDK 3.0 and later."
|
#warning "This project uses features only available in iPhone SDK 3.0 and later."
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue