Updated AFNetworking to version 2.4.1 to fix crash when building in Xcode 6

This commit is contained in:
CSullivan102
2014-09-22 00:05:07 -04:00
parent e562bd0627
commit be660f97d8
20 changed files with 1221 additions and 806 deletions
+1 -2
View File
@@ -1,6 +1,6 @@
// AFHTTPRequestOperation.h
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +22,6 @@
#import <Foundation/Foundation.h>
#import "AFURLConnectionOperation.h"
#import "AFURLResponseSerialization.h"
/**
`AFHTTPRequestOperation` is a subclass of `AFURLConnectionOperation` for requests using the HTTP or HTTPS protocols. It encapsulates the concept of acceptable status codes and content types, which determine the success or failure of a request.
+11 -7
View File
@@ -1,6 +1,6 @@
// AFHTTPRequestOperation.m
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -151,6 +151,8 @@ static dispatch_group_t http_request_operation_completion_group() {
#pragma mark - AFURLRequestOperation
- (void)pause {
[super pause];
u_int64_t offset = 0;
if ([self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey]) {
offset = [(NSNumber *)[self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey] unsignedLongLongValue];
@@ -164,11 +166,13 @@ static dispatch_group_t http_request_operation_completion_group() {
}
[mutableURLRequest setValue:[NSString stringWithFormat:@"bytes=%llu-", offset] forHTTPHeaderField:@"Range"];
self.request = mutableURLRequest;
[super pause];
}
#pragma mark - NSCoding
#pragma mark - NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
@@ -176,7 +180,7 @@ static dispatch_group_t http_request_operation_completion_group() {
return nil;
}
self.responseSerializer = [decoder decodeObjectForKey:NSStringFromSelector(@selector(responseSerializer))];
self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))];
return self;
}
@@ -190,12 +194,12 @@ static dispatch_group_t http_request_operation_completion_group() {
#pragma mark - NSCopying
- (id)copyWithZone:(NSZone *)zone {
AFHTTPRequestOperation *operation = [[[self class] allocWithZone:zone] initWithRequest:self.request];
AFHTTPRequestOperation *operation = [super copyWithZone:zone];
operation.responseSerializer = [self.responseSerializer copyWithZone:zone];
operation.completionQueue = self.completionQueue;
operation.completionGroup = self.completionGroup;
return operation;
}
+26 -12
View File
@@ -1,6 +1,6 @@
// AFHTTPRequestOperationManager.h
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -75,14 +75,14 @@
Network reachability status and change monitoring is available through the `reachabilityManager` property. Applications may choose to monitor network reachability conditions in order to prevent or suspend any outbound requests. See `AFNetworkReachabilityManager` for more details.
## NSCoding & NSCopying Caveats
## NSSecureCoding & NSCopying Caveats
`AFHTTPRequestOperationManager` conforms to the `NSCoding` and `NSCopying` protocols, allowing operations to be archived to disk, and copied in memory, respectively. There are a few minor caveats to keep in mind, however:
`AFHTTPRequestOperationManager` conforms to the `NSSecureCoding` and `NSCopying` protocols, allowing operations to be archived to disk, and copied in memory, respectively. There are a few minor caveats to keep in mind, however:
- Archives and copies of HTTP clients will be initialized with an empty operation queue.
- NSCoding cannot serialize / deserialize block properties, so an archive of an HTTP client will not include any reachability callback block that may be set.
- NSSecureCoding cannot serialize / deserialize block properties, so an archive of an HTTP client will not include any reachability callback block that may be set.
*/
@interface AFHTTPRequestOperationManager : NSObject <NSCoding, NSCopying>
@interface AFHTTPRequestOperationManager : NSObject <NSSecureCoding, NSCopying>
/**
The URL used to monitor reachability, and construct requests from relative paths in methods like `requestWithMethod:URLString:parameters:`, and the `GET` / `POST` / et al. convenience methods.
@@ -144,6 +144,20 @@
*/
@property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager;
///-------------------------------
/// @name Managing Callback Queues
///-------------------------------
/**
The dispatch queue for the `completionBlock` of request operations. If `NULL` (default), the main queue is used.
*/
@property (nonatomic, strong) dispatch_queue_t completionQueue;
/**
The dispatch group for the `completionBlock` of request operations. If `NULL` (default), a private dispatch group is used.
*/
@property (nonatomic, strong) dispatch_group_t completionGroup;
///---------------------------------------------
/// @name Creating and Initializing HTTP Clients
///---------------------------------------------
@@ -194,7 +208,7 @@
@see -HTTPRequestOperationWithRequest:success:failure:
*/
- (AFHTTPRequestOperation *)GET:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
@@ -209,7 +223,7 @@
@see -HTTPRequestOperationWithRequest:success:failure:
*/
- (AFHTTPRequestOperation *)HEAD:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
@@ -224,7 +238,7 @@
@see -HTTPRequestOperationWithRequest:success:failure:
*/
- (AFHTTPRequestOperation *)POST:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
@@ -240,7 +254,7 @@
@see -HTTPRequestOperationWithRequest:success:failure:
*/
- (AFHTTPRequestOperation *)POST:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
@@ -256,7 +270,7 @@
@see -HTTPRequestOperationWithRequest:success:failure:
*/
- (AFHTTPRequestOperation *)PUT:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
@@ -271,7 +285,7 @@
@see -HTTPRequestOperationWithRequest:success:failure:
*/
- (AFHTTPRequestOperation *)PATCH:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
@@ -286,7 +300,7 @@
@see -HTTPRequestOperationWithRequest:success:failure:
*/
- (AFHTTPRequestOperation *)DELETE:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
+31 -16
View File
@@ -1,6 +1,6 @@
// AFHTTPRequestOperationManager.m
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -39,7 +39,7 @@
@implementation AFHTTPRequestOperationManager
+ (instancetype)manager {
return [[[self class] alloc] initWithBaseURL:nil];
return [[self alloc] initWithBaseURL:nil];
}
- (instancetype)init {
@@ -73,10 +73,6 @@
return self;
}
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.operationQueue];
}
#pragma mark -
#ifdef _SYSTEMCONFIGURATION_H
@@ -107,6 +103,8 @@
operation.securityPolicy = self.securityPolicy;
[operation setCompletionBlockWithSuccess:success failure:failure];
operation.completionQueue = self.completionQueue;
operation.completionGroup = self.completionGroup;
return operation;
}
@@ -114,19 +112,20 @@
#pragma mark -
- (AFHTTPRequestOperation *)GET:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"GET" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
[self.operationQueue addOperation:operation];
return operation;
}
- (AFHTTPRequestOperation *)HEAD:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
@@ -136,73 +135,89 @@
success(requestOperation);
}
} failure:failure];
[self.operationQueue addOperation:operation];
return operation;
}
- (AFHTTPRequestOperation *)POST:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
[self.operationQueue addOperation:operation];
return operation;
}
- (AFHTTPRequestOperation *)POST:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:nil];
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
[self.operationQueue addOperation:operation];
return operation;
}
- (AFHTTPRequestOperation *)PUT:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"PUT" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
[self.operationQueue addOperation:operation];
return operation;
}
- (AFHTTPRequestOperation *)PATCH:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"PATCH" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
[self.operationQueue addOperation:operation];
return operation;
}
- (AFHTTPRequestOperation *)DELETE:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"DELETE" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
[self.operationQueue addOperation:operation];
return operation;
}
#pragma mark - NSCoding
#pragma mark - NSObject
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.operationQueue];
}
#pragma mark - NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (id)initWithCoder:(NSCoder *)decoder {
NSURL *baseURL = [decoder decodeObjectForKey:NSStringFromSelector(@selector(baseURL))];
@@ -212,8 +227,8 @@
return nil;
}
self.requestSerializer = [decoder decodeObjectForKey:NSStringFromSelector(@selector(requestSerializer))];
self.responseSerializer = [decoder decodeObjectForKey:NSStringFromSelector(@selector(responseSerializer))];
self.requestSerializer = [decoder decodeObjectOfClass:[AFHTTPRequestSerializer class] forKey:NSStringFromSelector(@selector(requestSerializer))];
self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))];
return self;
}
+9 -9
View File
@@ -1,6 +1,6 @@
// AFHTTPSessionManager.h
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -70,7 +70,7 @@
#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090)
@interface AFHTTPSessionManager : AFURLSessionManager <NSCoding, NSCopying>
@interface AFHTTPSessionManager : AFURLSessionManager <NSSecureCoding, NSCopying>
/**
The URL used to monitor reachability, and construct requests from relative paths in methods like `requestWithMethod:URLString:parameters:`, and the `GET` / `POST` / et al. convenience methods.
@@ -137,7 +137,7 @@
@see -dataTaskWithRequest:completionHandler:
*/
- (NSURLSessionDataTask *)GET:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;
@@ -152,7 +152,7 @@
@see -dataTaskWithRequest:completionHandler:
*/
- (NSURLSessionDataTask *)HEAD:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;
@@ -167,7 +167,7 @@
@see -dataTaskWithRequest:completionHandler:
*/
- (NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;
@@ -183,7 +183,7 @@
@see -dataTaskWithRequest:completionHandler:
*/
- (NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;
@@ -199,7 +199,7 @@
@see -dataTaskWithRequest:completionHandler:
*/
- (NSURLSessionDataTask *)PUT:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;
@@ -214,7 +214,7 @@
@see -dataTaskWithRequest:completionHandler:
*/
- (NSURLSessionDataTask *)PATCH:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;
@@ -229,7 +229,7 @@
@see -dataTaskWithRequest:completionHandler:
*/
- (NSURLSessionDataTask *)DELETE:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;
+94 -101
View File
@@ -1,6 +1,6 @@
// AFHTTPSessionManager.m
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -24,7 +24,8 @@
#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090)
#import "AFHTTPRequestOperation.h"
#import "AFURLRequestSerialization.h"
#import "AFURLResponseSerialization.h"
#import <Availability.h>
#import <Security/Security.h>
@@ -84,10 +85,6 @@
return self;
}
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.session, self.operationQueue];
}
#pragma mark -
#ifdef _SYSTEMCONFIGURATION_H
@@ -108,84 +105,65 @@
#pragma mark -
- (NSURLSessionDataTask *)GET:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"GET" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET" URLString:URLString parameters:parameters success:success failure:failure];
__block NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
if (error) {
if (failure) {
failure(task, error);
}
} else {
if (success) {
success(task, responseObject);
}
}
}];
[dataTask resume];
[task resume];
return task;
return dataTask;
}
- (NSURLSessionDataTask *)HEAD:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"HEAD" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
__block NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id __unused responseObject, NSError *error) {
if (error) {
if (failure) {
failure(task, error);
}
} else {
if (success) {
success(task);
}
NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"HEAD" URLString:URLString parameters:parameters success:^(NSURLSessionDataTask *task, __unused id responseObject) {
if (success) {
success(task);
}
}];
} failure:failure];
[task resume];
[dataTask resume];
return task;
return dataTask;
}
- (NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters success:success failure:failure];
__block NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
if (error) {
if (failure) {
failure(task, error);
}
} else {
if (success) {
success(task, responseObject);
}
}
}];
[dataTask resume];
[task resume];
return task;
return dataTask;
}
- (NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:nil];
NSError *serializationError = nil;
NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError];
if (serializationError) {
if (failure) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(nil, serializationError);
});
#pragma clang diagnostic pop
}
return nil;
}
__block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:nil completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
if (error) {
@@ -205,86 +183,101 @@
}
- (NSURLSessionDataTask *)PUT:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"PUT" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PUT" URLString:URLString parameters:parameters success:success failure:failure];
__block NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
if (error) {
if (failure) {
failure(task, error);
}
} else {
if (success) {
success(task, responseObject);
}
}
}];
[dataTask resume];
[task resume];
return task;
return dataTask;
}
- (NSURLSessionDataTask *)PATCH:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"PATCH" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PATCH" URLString:URLString parameters:parameters success:success failure:failure];
__block NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
if (error) {
if (failure) {
failure(task, error);
}
} else {
if (success) {
success(task, responseObject);
}
}
}];
[dataTask resume];
[task resume];
return task;
return dataTask;
}
- (NSURLSessionDataTask *)DELETE:(NSString *)URLString
parameters:(NSDictionary *)parameters
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"DELETE" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"DELETE" URLString:URLString parameters:parameters success:success failure:failure];
__block NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
[dataTask resume];
return dataTask;
}
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *, id))success
failure:(void (^)(NSURLSessionDataTask *, NSError *))failure
{
NSError *serializationError = nil;
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
if (serializationError) {
if (failure) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(nil, serializationError);
});
#pragma clang diagnostic pop
}
return nil;
}
__block NSURLSessionDataTask *dataTask = nil;
dataTask = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
if (error) {
if (failure) {
failure(task, error);
failure(dataTask, error);
}
} else {
if (success) {
success(task, responseObject);
success(dataTask, responseObject);
}
}
}];
[task resume];
return task;
return dataTask;
}
#pragma mark - NSCoding
#pragma mark - NSObject
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.session, self.operationQueue];
}
#pragma mark - NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (id)initWithCoder:(NSCoder *)decoder {
NSURL *baseURL = [decoder decodeObjectForKey:NSStringFromSelector(@selector(baseURL))];
NSURLSessionConfiguration *configuration = [decoder decodeObjectForKey:@"sessionConfiguration"];
NSURL *baseURL = [decoder decodeObjectOfClass:[NSURL class] forKey:NSStringFromSelector(@selector(baseURL))];
NSURLSessionConfiguration *configuration = [decoder decodeObjectOfClass:[NSURLSessionConfiguration class] forKey:@"sessionConfiguration"];
if (!configuration) {
NSString *configurationIdentifier = [decoder decodeObjectForKey:@"identifier"];
NSString *configurationIdentifier = [decoder decodeObjectOfClass:[NSString class] forKey:@"identifier"];
if (configurationIdentifier) {
#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1100)
configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:configurationIdentifier];
#else
configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:configurationIdentifier];
#endif
}
}
@@ -293,8 +286,8 @@
return nil;
}
self.requestSerializer = [decoder decodeObjectForKey:NSStringFromSelector(@selector(requestSerializer))];
self.responseSerializer = [decoder decodeObjectForKey:NSStringFromSelector(@selector(responseSerializer))];
self.requestSerializer = [decoder decodeObjectOfClass:[AFHTTPRequestSerializer class] forKey:NSStringFromSelector(@selector(requestSerializer))];
self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))];
return self;
}
+5 -9
View File
@@ -1,6 +1,6 @@
// AFNetworkReachabilityManager.h
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -23,12 +23,6 @@
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <netinet/in.h>
#import <netinet6/in6.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
AFNetworkReachabilityStatusUnknown = -1,
AFNetworkReachabilityStatusNotReachable = 0,
@@ -39,6 +33,8 @@ typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
/**
`AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces.
Reachability can be used to determine background information about why a network operation failed, or to trigger a network operation retrying when a connection is established. It should not be used to prevent a user from initiating a network request, as it's possible that an initial request may be required to establish reachability.
See Apple's Reachability Sample Code (https://developer.apple.com/library/ios/samplecode/reachability/)
@warning Instances of `AFNetworkReachabilityManager` must be started with `-startMonitoring` before reachability status can be determined.
@@ -86,11 +82,11 @@ typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
/**
Creates and returns a network reachability manager for the socket address.
@param address The socket address used to evaluate network reachability.
@param address The socket address (`sockaddr_in`) used to evaluate network reachability.
@return An initialized network reachability manager, actively monitoring the specified socket address.
*/
+ (instancetype)managerForAddress:(const struct sockaddr_in *)address;
+ (instancetype)managerForAddress:(const void *)address;
/**
Initializes an instance of a network reachability manager from the specified reachability object.
+15 -2
View File
@@ -1,6 +1,6 @@
// AFNetworkReachabilityManager.m
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,12 @@
#import "AFNetworkReachabilityManager.h"
#import <netinet/in.h>
#import <netinet6/in6.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change";
NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem";
@@ -82,6 +88,7 @@ static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused targ
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:@{ AFNetworkingReachabilityNotificationStatusItem: @(status) }];
});
}
static const void * AFNetworkReachabilityRetainCallback(const void *info) {
@@ -127,7 +134,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
return manager;
}
+ (instancetype)managerForAddress:(const struct sockaddr_in *)address {
+ (instancetype)managerForAddress:(const void *)address {
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address);
AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
@@ -188,6 +195,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
if (strongSelf.networkReachabilityStatusBlock) {
strongSelf.networkReachabilityStatusBlock(status);
}
};
SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
@@ -206,6 +214,11 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
dispatch_async(dispatch_get_main_queue(), ^{
callback(status);
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:@{ AFNetworkingReachabilityNotificationStatusItem: @(status) }];
});
});
}
View File
+1 -1
View File
@@ -1,6 +1,6 @@
// AFSecurity.h
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
+85 -60
View File
@@ -1,6 +1,6 @@
// AFSecurity.m
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,20 +22,40 @@
#import "AFSecurityPolicy.h"
// Equivalent of macro in <AssertMacros.h>, without causing compiler warning:
// "'DebugAssert' is deprecated: first deprecated in OS X 10.8"
#ifndef AF_Require
#define AF_Require(assertion, exceptionLabel) \
do { \
if (__builtin_expect(!(assertion), 0)) { \
goto exceptionLabel; \
} \
} while (0)
#endif
#ifndef AF_Require_noErr
#define AF_Require_noErr(errorCode, exceptionLabel) \
do { \
if (__builtin_expect(0 != (errorCode), 0)) { \
goto exceptionLabel; \
} \
} while (0)
#endif
#if !defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
static NSData * AFSecKeyGetData(SecKeyRef key) {
CFDataRef data = NULL;
#if defined(NS_BLOCK_ASSERTIONS)
SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data);
#else
OSStatus status = SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data);
NSCAssert(status == errSecSuccess, @"SecItemExport error: %ld", (long int)status);
#endif
NSCParameterAssert(data);
AF_Require_noErr(SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data), _out);
return (__bridge_transfer NSData *)data;
_out:
if (data) {
CFRelease(data);
}
return nil;
}
#endif
@@ -48,52 +68,55 @@ static BOOL AFSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2) {
}
static id AFPublicKeyForCertificate(NSData *certificate) {
SecCertificateRef allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate);
NSCParameterAssert(allowedCertificate);
id allowedPublicKey = nil;
SecCertificateRef allowedCertificate;
SecCertificateRef allowedCertificates[1];
CFArrayRef tempCertificates = nil;
SecPolicyRef policy = nil;
SecTrustRef allowedTrust = nil;
SecTrustResultType result;
SecCertificateRef allowedCertificates[] = {allowedCertificate};
CFArrayRef tempCertificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL);
allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate);
AF_Require(allowedCertificate != NULL, _out);
SecPolicyRef policy = SecPolicyCreateBasicX509();
SecTrustRef allowedTrust = NULL;
#if defined(NS_BLOCK_ASSERTIONS)
SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust);
#else
OSStatus status = SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust);
NSCAssert(status == errSecSuccess, @"SecTrustCreateWithCertificates error: %ld", (long int)status);
#endif
allowedCertificates[0] = allowedCertificate;
tempCertificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL);
SecTrustResultType result = 0;
policy = SecPolicyCreateBasicX509();
AF_Require_noErr(SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust), _out);
AF_Require_noErr(SecTrustEvaluate(allowedTrust, &result), _out);
#if defined(NS_BLOCK_ASSERTIONS)
SecTrustEvaluate(allowedTrust, &result);
#else
status = SecTrustEvaluate(allowedTrust, &result);
NSCAssert(status == errSecSuccess, @"SecTrustEvaluate error: %ld", (long int)status);
#endif
allowedPublicKey = (__bridge_transfer id)SecTrustCopyPublicKey(allowedTrust);
SecKeyRef allowedPublicKey = SecTrustCopyPublicKey(allowedTrust);
NSCParameterAssert(allowedPublicKey);
_out:
if (allowedTrust) {
CFRelease(allowedTrust);
}
CFRelease(allowedTrust);
CFRelease(policy);
CFRelease(tempCertificates);
CFRelease(allowedCertificate);
if (policy) {
CFRelease(policy);
}
return (__bridge_transfer id)allowedPublicKey;
if (tempCertificates) {
CFRelease(tempCertificates);
}
if (allowedCertificate) {
CFRelease(allowedCertificate);
}
return allowedPublicKey;
}
static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) {
SecTrustResultType result = 0;
BOOL isValid = NO;
SecTrustResultType result;
AF_Require_noErr(SecTrustEvaluate(serverTrust, &result), _out);
#if defined(NS_BLOCK_ASSERTIONS)
SecTrustEvaluate(serverTrust, &result);
#else
OSStatus status = SecTrustEvaluate(serverTrust, &result);
NSCAssert(status == errSecSuccess, @"SecTrustEvaluate error: %ld", (long int)status);
#endif
isValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
_out:
return isValid;
}
static NSArray * AFCertificateTrustChainForServerTrust(SecTrustRef serverTrust) {
@@ -118,26 +141,24 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) {
SecCertificateRef someCertificates[] = {certificate};
CFArrayRef certificates = CFArrayCreate(NULL, (const void **)someCertificates, 1, NULL);
SecTrustRef trust = NULL;
#if defined(NS_BLOCK_ASSERTIONS)
SecTrustCreateWithCertificates(certificates, policy, &trust);
SecTrustRef trust;
AF_Require_noErr(SecTrustCreateWithCertificates(certificates, policy, &trust), _out);
SecTrustResultType result;
SecTrustEvaluate(trust, &result);
#else
OSStatus status = SecTrustCreateWithCertificates(certificates, policy, &trust);
NSCAssert(status == errSecSuccess, @"SecTrustCreateWithCertificates error: %ld", (long int)status);
SecTrustResultType result;
status = SecTrustEvaluate(trust, &result);
NSCAssert(status == errSecSuccess, @"SecTrustEvaluate error: %ld", (long int)status);
#endif
AF_Require_noErr(SecTrustEvaluate(trust, &result), _out);
[trustChain addObject:(__bridge_transfer id)SecTrustCopyPublicKey(trust)];
CFRelease(trust);
CFRelease(certificates);
_out:
if (trust) {
CFRelease(trust);
}
if (certificates) {
CFRelease(certificates);
}
continue;
}
CFRelease(policy);
@@ -206,7 +227,11 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) {
if (self.pinnedCertificates) {
NSMutableArray *mutablePinnedPublicKeys = [NSMutableArray arrayWithCapacity:[self.pinnedCertificates count]];
for (NSData *certificate in self.pinnedCertificates) {
[mutablePinnedPublicKeys addObject:AFPublicKeyForCertificate(certificate)];
id publicKey = AFPublicKeyForCertificate(certificate);
if (!publicKey) {
continue;
}
[mutablePinnedPublicKeys addObject:publicKey];
}
self.pinnedPublicKeys = [NSArray arrayWithArray:mutablePinnedPublicKeys];
} else {
+13 -42
View File
@@ -1,6 +1,6 @@
// AFURLConnectionOperation.h
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -23,6 +23,8 @@
#import <Foundation/Foundation.h>
#import <Availability.h>
#import "AFURLRequestSerialization.h"
#import "AFURLResponseSerialization.h"
#import "AFSecurityPolicy.h"
/**
@@ -63,6 +65,10 @@
SSL with certificate pinning is strongly recommended for any application that transmits sensitive information to an external webservice.
Connections will be validated on all matching certificates with a `.cer` extension in the bundle root.
## App Extensions
When using AFNetworking in an App Extension, `#define AF_APP_EXTENSIONS` to avoid using unavailable APIs.
## NSCoding & NSCopying Conformance
@@ -80,7 +86,7 @@
- Operation copies do not include `completionBlock`, as it 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, NSURLConnectionDataDelegate, NSCoding, NSCopying>
@interface AFURLConnectionOperation : NSOperation <NSURLConnectionDelegate, NSURLConnectionDataDelegate, NSSecureCoding, NSCopying>
///-------------------------------
/// @name Accessing Run Loop Modes
@@ -172,7 +178,7 @@
/**
The output stream that is used to write data received until the request is finished.
By default, data is accumulated into a buffer that is stored into `responseData` upon completion of the request. When `outputStream` is set, the data will not be accumulated into an internal buffer, and as a result, the `responseData` property of the completed request will be `nil`. The output stream will be scheduled in the network thread runloop upon being set.
By default, data is accumulated into a buffer that is stored into `responseData` upon completion of the request, with the intermediary `outputStream` property set to `nil`. When `outputStream` is set, the data will not be accumulated into an internal buffer, and as a result, the `responseData` property of the completed request will be `nil`. The output stream will be scheduled in the network thread runloop upon being set.
*/
@property (nonatomic, strong) NSOutputStream *outputStream;
@@ -245,8 +251,8 @@
Specifies that the operation should continue execution after the app has entered the background, and the expiration handler for that background task.
@param handler A handler to be called shortly before the applications remaining background time reaches 0. The handler is wrapped in a block that cancels the operation, and cleans up and marks the end of execution, unlike the `handler` parameter in `UIApplication -beginBackgroundTaskWithExpirationHandler:`, which expects this to be done in the handler itself. The handler is called synchronously on the main thread, thus blocking the applications suspension momentarily while the application is notified.
*/
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
*/
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS)
- (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))handler;
#endif
@@ -259,14 +265,14 @@
@param block A block object to be called when an undetermined number of bytes have been uploaded to the server. This block has no return value and takes three arguments: the number of bytes written since the last time the upload progress block was called, the total bytes written, and the total bytes expected to be written during the request, as initially determined by the length of the HTTP body. This block may be called multiple times, and will execute on the main thread.
*/
- (void)setUploadProgressBlock:(void (^)(NSUInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite))block;
- (void)setUploadProgressBlock:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))block;
/**
Sets a callback to be called when an undetermined number of bytes have been downloaded from the server.
@param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes three arguments: the number of bytes read since the last time the download progress block was called, the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times, and will execute on the main thread.
*/
- (void)setDownloadProgressBlock:(void (^)(NSUInteger bytesRead, NSInteger totalBytesRead, NSInteger totalBytesExpectedToRead))block;
- (void)setDownloadProgressBlock:(void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))block;
///-------------------------------------------------
/// @name Setting NSURLConnection Delegate Callbacks
@@ -307,41 +313,6 @@
@end
///----------------
/// @name Constants
///----------------
/**
## User info dictionary keys
These keys may exist in the user info dictionary, in addition to those defined for NSError.
- `NSString * const AFNetworkingOperationFailingURLRequestErrorKey`
- `NSString * const AFNetworkingOperationFailingURLResponseErrorKey`
### Constants
`AFNetworkingOperationFailingURLRequestErrorKey`
The corresponding value is an `NSURLRequest` containing the request of the operation associated with an error. This key is only present in the `AFNetworkingErrorDomain`.
`AFNetworkingOperationFailingURLResponseErrorKey`
The corresponding value is an `NSURLResponse` containing the response of the operation associated with an error. This key is only present in the `AFNetworkingErrorDomain`.
## Error Domains
The following error domain is predefined.
- `NSString * const AFNetworkingErrorDomain`
### Constants
`AFNetworkingErrorDomain`
AFNetworking errors. Error codes for `AFNetworkingErrorDomain` correspond to codes in `NSURLErrorDomain`.
*/
extern NSString * const AFNetworkingErrorDomain;
extern NSString * const AFNetworkingOperationFailingURLRequestErrorKey;
extern NSString * const AFNetworkingOperationFailingURLResponseErrorKey;
///--------------------
/// @name Notifications
///--------------------
+238 -204
View File
@@ -1,6 +1,6 @@
// AFURLConnectionOperation.m
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -38,7 +38,7 @@ typedef NS_ENUM(NSInteger, AFOperationState) {
AFOperationFinishedState = 3,
};
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS)
typedef UIBackgroundTaskIdentifier AFBackgroundTaskIdentifier;
#else
typedef id AFBackgroundTaskIdentifier;
@@ -66,14 +66,10 @@ static dispatch_queue_t url_request_operation_completion_queue() {
static NSString * const kAFNetworkingLockName = @"com.alamofire.networking.operation.lock";
NSString * const AFNetworkingErrorDomain = @"AFNetworkingErrorDomain";
NSString * const AFNetworkingOperationFailingURLRequestErrorKey = @"AFNetworkingOperationFailingURLRequestErrorKey";
NSString * const AFNetworkingOperationFailingURLResponseErrorKey = @"AFNetworkingOperationFailingURLResponseErrorKey";
NSString * const AFNetworkingOperationDidStartNotification = @"com.alamofire.networking.operation.start";
NSString * const AFNetworkingOperationDidFinishNotification = @"com.alamofire.networking.operation.finish";
typedef void (^AFURLConnectionOperationProgressBlock)(NSUInteger bytes, NSInteger totalBytes, NSInteger totalBytesExpected);
typedef void (^AFURLConnectionOperationProgressBlock)(NSUInteger bytes, long long totalBytes, long long totalBytesExpected);
typedef void (^AFURLConnectionOperationAuthenticationChallengeBlock)(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge);
typedef NSCachedURLResponse * (^AFURLConnectionOperationCacheResponseBlock)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse);
typedef NSURLRequest * (^AFURLConnectionOperationRedirectResponseBlock)(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse);
@@ -121,8 +117,20 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
return NO;
case AFOperationPausedState:
return toState == AFOperationReadyState;
default:
return YES;
default: {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
switch (toState) {
case AFOperationPausedState:
case AFOperationReadyState:
case AFOperationExecutingState:
case AFOperationFinishedState:
return YES;
default:
return NO;
}
}
#pragma clang diagnostic pop
}
}
@@ -136,7 +144,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
@property (readwrite, nonatomic, strong) NSData *responseData;
@property (readwrite, nonatomic, copy) NSString *responseString;
@property (readwrite, nonatomic, assign) NSStringEncoding responseStringEncoding;
@property (readwrite, nonatomic, assign) NSInteger totalBytesRead;
@property (readwrite, nonatomic, assign) long long totalBytesRead;
@property (readwrite, nonatomic, assign) AFBackgroundTaskIdentifier backgroundTaskIdentifier;
@property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock uploadProgress;
@property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock downloadProgress;
@@ -180,7 +188,9 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
if (!self) {
return nil;
}
_state = AFOperationReadyState;
self.lock = [[NSRecursiveLock alloc] init];
self.lock.name = kAFNetworkingLockName;
@@ -190,8 +200,6 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
self.shouldUseCredentialStorage = YES;
self.state = AFOperationReadyState;
self.securityPolicy = [AFSecurityPolicy defaultPolicy];
return self;
@@ -203,7 +211,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
_outputStream = nil;
}
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS)
if (_backgroundTaskIdentifier) {
[[UIApplication sharedApplication] endBackgroundTask:_backgroundTaskIdentifier];
_backgroundTaskIdentifier = UIBackgroundTaskInvalid;
@@ -211,10 +219,185 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
#endif
}
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p, state: %@, cancelled: %@ request: %@, response: %@>", NSStringFromClass([self class]), self, AFKeyPathFromOperationState(self.state), ([self isCancelled] ? @"YES" : @"NO"), self.request, self.response];
#pragma mark -
- (void)setResponseData:(NSData *)responseData {
[self.lock lock];
if (!responseData) {
_responseData = nil;
} else {
_responseData = [NSData dataWithBytes:responseData.bytes length:responseData.length];
}
[self.lock unlock];
}
- (NSString *)responseString {
[self.lock lock];
if (!_responseString && self.response && self.responseData) {
self.responseString = [[NSString alloc] initWithData:self.responseData encoding:self.responseStringEncoding];
}
[self.lock unlock];
return _responseString;
}
- (NSStringEncoding)responseStringEncoding {
[self.lock lock];
if (!_responseStringEncoding && self.response) {
NSStringEncoding stringEncoding = NSUTF8StringEncoding;
if (self.response.textEncodingName) {
CFStringEncoding IANAEncoding = CFStringConvertIANACharSetNameToEncoding((__bridge CFStringRef)self.response.textEncodingName);
if (IANAEncoding != kCFStringEncodingInvalidId) {
stringEncoding = CFStringConvertEncodingToNSStringEncoding(IANAEncoding);
}
}
self.responseStringEncoding = stringEncoding;
}
[self.lock unlock];
return _responseStringEncoding;
}
- (NSInputStream *)inputStream {
return self.request.HTTPBodyStream;
}
- (void)setInputStream:(NSInputStream *)inputStream {
NSMutableURLRequest *mutableRequest = [self.request mutableCopy];
mutableRequest.HTTPBodyStream = inputStream;
self.request = mutableRequest;
}
- (NSOutputStream *)outputStream {
if (!_outputStream) {
self.outputStream = [NSOutputStream outputStreamToMemory];
}
return _outputStream;
}
- (void)setOutputStream:(NSOutputStream *)outputStream {
[self.lock lock];
if (outputStream != _outputStream) {
if (_outputStream) {
[_outputStream close];
}
_outputStream = outputStream;
}
[self.lock unlock];
}
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS)
- (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))handler {
[self.lock lock];
if (!self.backgroundTaskIdentifier) {
UIApplication *application = [UIApplication sharedApplication];
__weak __typeof(self)weakSelf = self;
self.backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
if (handler) {
handler();
}
if (strongSelf) {
[strongSelf cancel];
[application endBackgroundTask:strongSelf.backgroundTaskIdentifier];
strongSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid;
}
}];
}
[self.lock unlock];
}
#endif
#pragma mark -
- (void)setState:(AFOperationState)state {
if (!AFStateTransitionIsValid(self.state, state, [self isCancelled])) {
return;
}
[self.lock lock];
NSString *oldStateKey = AFKeyPathFromOperationState(self.state);
NSString *newStateKey = AFKeyPathFromOperationState(state);
[self willChangeValueForKey:newStateKey];
[self willChangeValueForKey:oldStateKey];
_state = state;
[self didChangeValueForKey:oldStateKey];
[self didChangeValueForKey:newStateKey];
[self.lock unlock];
}
- (void)pause {
if ([self isPaused] || [self isFinished] || [self isCancelled]) {
return;
}
[self.lock lock];
if ([self isExecuting]) {
[self performSelector:@selector(operationDidPause) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
dispatch_async(dispatch_get_main_queue(), ^{
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
});
}
self.state = AFOperationPausedState;
[self.lock unlock];
}
- (void)operationDidPause {
[self.lock lock];
[self.connection cancel];
[self.lock unlock];
}
- (BOOL)isPaused {
return self.state == AFOperationPausedState;
}
- (void)resume {
if (![self isPaused]) {
return;
}
[self.lock lock];
self.state = AFOperationReadyState;
[self start];
[self.lock unlock];
}
#pragma mark -
- (void)setUploadProgressBlock:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))block {
self.uploadProgress = block;
}
- (void)setDownloadProgressBlock:(void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))block {
self.downloadProgress = block;
}
- (void)setWillSendRequestForAuthenticationChallengeBlock:(void (^)(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge))block {
self.authenticationChallenge = block;
}
- (void)setCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse))block {
self.cacheResponse = block;
}
- (void)setRedirectResponseBlock:(NSURLRequest * (^)(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse))block {
self.redirectResponse = block;
}
#pragma mark - NSOperation
- (void)setCompletionBlock:(void (^)(void))block {
[self.lock lock];
if (!block) {
@@ -242,170 +425,6 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
[self.lock unlock];
}
- (NSInputStream *)inputStream {
return self.request.HTTPBodyStream;
}
- (void)setInputStream:(NSInputStream *)inputStream {
NSMutableURLRequest *mutableRequest = [self.request mutableCopy];
mutableRequest.HTTPBodyStream = inputStream;
self.request = mutableRequest;
}
- (NSOutputStream *)outputStream {
if (!_outputStream) {
self.outputStream = [NSOutputStream outputStreamToMemory];
}
return _outputStream;
}
- (void)setOutputStream:(NSOutputStream *)outputStream {
[self.lock lock];
if (outputStream != _outputStream) {
if (_outputStream) {
[_outputStream close];
}
_outputStream = outputStream;
}
[self.lock unlock];
}
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
- (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))handler {
[self.lock lock];
if (!self.backgroundTaskIdentifier) {
UIApplication *application = [UIApplication sharedApplication];
__weak __typeof(self)weakSelf = self;
self.backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
if (handler) {
handler();
}
if (strongSelf) {
[strongSelf cancel];
[application endBackgroundTask:strongSelf.backgroundTaskIdentifier];
strongSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid;
}
}];
}
[self.lock unlock];
}
#endif
- (void)setUploadProgressBlock:(void (^)(NSUInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite))block {
self.uploadProgress = block;
}
- (void)setDownloadProgressBlock:(void (^)(NSUInteger bytesRead, NSInteger totalBytesRead, NSInteger totalBytesExpectedToRead))block {
self.downloadProgress = block;
}
- (void)setWillSendRequestForAuthenticationChallengeBlock:(void (^)(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge))block {
self.authenticationChallenge = block;
}
- (void)setCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse))block {
self.cacheResponse = block;
}
- (void)setRedirectResponseBlock:(NSURLRequest * (^)(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse))block {
self.redirectResponse = block;
}
- (void)setState:(AFOperationState)state {
if (!AFStateTransitionIsValid(self.state, state, [self isCancelled])) {
return;
}
[self.lock lock];
NSString *oldStateKey = AFKeyPathFromOperationState(self.state);
NSString *newStateKey = AFKeyPathFromOperationState(state);
[self willChangeValueForKey:newStateKey];
[self willChangeValueForKey:oldStateKey];
_state = state;
[self didChangeValueForKey:oldStateKey];
[self didChangeValueForKey:newStateKey];
[self.lock unlock];
}
- (NSString *)responseString {
[self.lock lock];
if (!_responseString && self.response && self.responseData) {
self.responseString = [[NSString alloc] initWithData:self.responseData encoding:self.responseStringEncoding];
}
[self.lock unlock];
return _responseString;
}
- (NSStringEncoding)responseStringEncoding {
[self.lock lock];
if (!_responseStringEncoding && self.response) {
NSStringEncoding stringEncoding = NSUTF8StringEncoding;
if (self.response.textEncodingName) {
CFStringEncoding IANAEncoding = CFStringConvertIANACharSetNameToEncoding((__bridge CFStringRef)self.response.textEncodingName);
if (IANAEncoding != kCFStringEncodingInvalidId) {
stringEncoding = CFStringConvertEncodingToNSStringEncoding(IANAEncoding);
}
}
self.responseStringEncoding = stringEncoding;
}
[self.lock unlock];
return _responseStringEncoding;
}
- (void)pause {
if ([self isPaused] || [self isFinished] || [self isCancelled]) {
return;
}
[self.lock lock];
if ([self isExecuting]) {
[self performSelector:@selector(operationDidPause) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
dispatch_async(dispatch_get_main_queue(), ^{
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
});
}
self.state = AFOperationPausedState;
[self.lock unlock];
}
- (void)operationDidPause {
[self.lock lock];
[self.connection cancel];
[self.lock unlock];
}
- (BOOL)isPaused {
return self.state == AFOperationPausedState;
}
- (void)resume {
if (![self isPaused]) {
return;
}
[self.lock lock];
self.state = AFOperationReadyState;
[self start];
[self.lock unlock];
}
#pragma mark - NSOperation
- (BOOL)isReady {
return self.state == AFOperationReadyState && [super isReady];
}
@@ -445,6 +464,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
[self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode];
}
[self.outputStream open];
[self.connection start];
}
[self.lock unlock];
@@ -554,6 +574,12 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
return [operations arrayByAddingObject:batchedOperation];
}
#pragma mark - NSObject
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p, state: %@, cancelled: %@ request: %@, response: %@>", NSStringFromClass([self class]), self, AFKeyPathFromOperationState(self.state), ([self isCancelled] ? @"YES" : @"NO"), self.request, self.response];
}
#pragma mark - NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection
@@ -604,19 +630,17 @@ willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challe
totalBytesWritten:(NSInteger)totalBytesWritten
totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
if (self.uploadProgress) {
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_main_queue(), ^{
if (self.uploadProgress) {
self.uploadProgress((NSUInteger)bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
});
}
}
});
}
- (void)connection:(NSURLConnection __unused *)connection
didReceiveResponse:(NSURLResponse *)response
{
self.response = response;
[self.outputStream open];
}
- (void)connection:(NSURLConnection __unused *)connection
@@ -649,34 +673,40 @@ didReceiveResponse:(NSURLResponse *)response
}
dispatch_async(dispatch_get_main_queue(), ^{
self.totalBytesRead += (NSInteger)length;
self.totalBytesRead += (long long)length;
if (self.downloadProgress) {
self.downloadProgress(length, self.totalBytesRead, (NSInteger)self.response.expectedContentLength);
self.downloadProgress(length, self.totalBytesRead, self.response.expectedContentLength);
}
});
}
- (void)connectionDidFinishLoading:(NSURLConnection __unused *)connection {
self.responseData = [self.outputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
[self.outputStream close];
[self finish];
if (self.responseData) {
self.outputStream = nil;
}
self.connection = nil;
[self finish];
}
- (void)connection:(NSURLConnection __unused *)connection
didFailWithError:(NSError *)error
{
self.error = error;
[self.outputStream close];
[self finish];
if (self.responseData) {
self.outputStream = nil;
}
self.connection = nil;
[self finish];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
@@ -693,21 +723,25 @@ didReceiveResponse:(NSURLResponse *)response
}
}
#pragma mark - NSCoding
#pragma mark - NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (id)initWithCoder:(NSCoder *)decoder {
NSURLRequest *request = [decoder decodeObjectForKey:NSStringFromSelector(@selector(request))];
NSURLRequest *request = [decoder decodeObjectOfClass:[NSURLRequest class] forKey:NSStringFromSelector(@selector(request))];
self = [self initWithRequest:request];
if (!self) {
return nil;
}
self.state = (AFOperationState)[decoder decodeIntegerForKey:NSStringFromSelector(@selector(state))];
self.response = [decoder decodeObjectForKey:NSStringFromSelector(@selector(response))];
self.error = [decoder decodeObjectForKey:NSStringFromSelector(@selector(error))];
self.responseData = [decoder decodeObjectForKey:NSStringFromSelector(@selector(responseData))];
self.totalBytesRead = [decoder decodeIntegerForKey:NSStringFromSelector(@selector(totalBytesRead))];
self.state = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(state))] integerValue];
self.response = [decoder decodeObjectOfClass:[NSHTTPURLResponse class] forKey:NSStringFromSelector(@selector(response))];
self.error = [decoder decodeObjectOfClass:[NSError class] forKey:NSStringFromSelector(@selector(error))];
self.responseData = [decoder decodeObjectOfClass:[NSData class] forKey:NSStringFromSelector(@selector(responseData))];
self.totalBytesRead = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(totalBytesRead))] longLongValue];
return self;
}
+63 -27
View File
@@ -1,6 +1,6 @@
// AFSerialization.h
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -30,7 +30,7 @@
For example, a JSON request serializer may set the HTTP body of the request to a JSON representation, and set the `Content-Type` HTTP header field value to `application/json`.
*/
@protocol AFURLRequestSerialization <NSObject, NSCoding, NSCopying>
@protocol AFURLRequestSerialization <NSObject, NSSecureCoding, NSCopying>
/**
Returns a request with the specified parameters encoded into a copy of the original request.
@@ -135,6 +135,15 @@ typedef NS_ENUM(NSUInteger, AFHTTPRequestQueryStringSerializationStyle) {
- (void)setValue:(NSString *)value
forHTTPHeaderField:(NSString *)field;
/**
Returns the value for the HTTP headers set in the request serializer.
@param field The HTTP header to retrieve the default value for
@return The value set as default for the specified header, or `nil`
*/
- (NSString *)valueForHTTPHeaderField:(NSString *)field;
/**
Sets the "Authorization" HTTP header set in request objects made by the HTTP client to a basic authentication value with Base64-encoded username and password. This overwrites any existing value for this header.
@@ -145,11 +154,9 @@ forHTTPHeaderField:(NSString *)field;
password:(NSString *)password;
/**
Sets the "Authorization" HTTP header set in request objects made by the HTTP client to a token-based authentication value, such as an OAuth access token. This overwrites any existing value for this header.
@param token The authentication token
@deprecated This method has been deprecated. Use -setValue:forHTTPHeaderField: instead.
*/
- (void)setAuthorizationHeaderFieldWithToken:(NSString *)token;
- (void)setAuthorizationHeaderFieldWithToken:(NSString *)token DEPRECATED_ATTRIBUTE;
/**
@@ -256,9 +263,6 @@ forHTTPHeaderField:(NSString *)field;
#pragma mark -
extern NSUInteger const kAFUploadStream3GSuggestedPacketSize;
extern NSTimeInterval const kAFUploadStream3GSuggestedDelay;
/**
The `AFMultipartFormData` protocol defines the methods supported by the parameter in the block argument of `AFHTTPRequestSerializer -multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:`.
*/
@@ -308,7 +312,7 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay;
- (void)appendPartWithInputStream:(NSInputStream *)inputStream
name:(NSString *)name
fileName:(NSString *)fileName
length:(NSUInteger)length
length:(int64_t)length
mimeType:(NSString *)mimeType;
/**
@@ -339,7 +343,7 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay;
Appends HTTP headers, followed by the encoded data and the multipart form boundary.
@param headers The HTTP headers to be appended to the form data.
@param body The data to be encoded and appended to the form data.
@param body The data to be encoded and appended to the form data. This parameter must not be `nil`.
*/
- (void)appendPartWithHeaders:(NSDictionary *)headers
body:(NSData *)body;
@@ -357,22 +361,6 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay;
@end
///----------------
/// @name Constants
///----------------
/**
## Throttling Bandwidth for HTTP Request Input Streams
@see -throttleBandwidthWithPacketSize:delay:
`kAFUploadStream3GSuggestedPacketSize`
Maximum packet size, in number of bytes. Equal to 16kb.
`kAFUploadStream3GSuggestedDelay`
Duration of delay each time a packet is read. Equal to 0.2 seconds.
*/
#pragma mark -
@interface AFJSONRequestSerializer : AFHTTPRequestSerializer
@@ -415,3 +403,51 @@ extern NSTimeInterval const kAFUploadStream3GSuggestedDelay;
writeOptions:(NSPropertyListWriteOptions)writeOptions;
@end
///----------------
/// @name Constants
///----------------
/**
## Error Domains
The following error domain is predefined.
- `NSString * const AFURLRequestSerializationErrorDomain`
### Constants
`AFURLRequestSerializationErrorDomain`
AFURLRequestSerializer errors. Error codes for `AFURLRequestSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`.
*/
extern NSString * const AFURLRequestSerializationErrorDomain;
/**
## User info dictionary keys
These keys may exist in the user info dictionary, in addition to those defined for NSError.
- `NSString * const AFNetworkingOperationFailingURLResponseErrorKey`
### Constants
`AFNetworkingOperationFailingURLRequestErrorKey`
The corresponding value is an `NSURLRequest` containing the request of the operation associated with an error. This key is only present in the `AFURLRequestSerializationErrorDomain`.
*/
extern NSString * const AFNetworkingOperationFailingURLRequestErrorKey;
/**
## Throttling Bandwidth for HTTP Request Input Streams
@see -throttleBandwidthWithPacketSize:delay:
### Constants
`kAFUploadStream3GSuggestedPacketSize`
Maximum packet size, in number of bytes. Equal to 16kb.
`kAFUploadStream3GSuggestedDelay`
Duration of delay each time a packet is read. Equal to 0.2 seconds.
*/
extern NSUInteger const kAFUploadStream3GSuggestedPacketSize;
extern NSTimeInterval const kAFUploadStream3GSuggestedDelay;
+159 -81
View File
@@ -1,6 +1,6 @@
// AFSerialization.h
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +22,14 @@
#import "AFURLRequestSerialization.h"
extern NSString * const AFNetworkingErrorDomain;
#if __IPHONE_OS_VERSION_MIN_REQUIRED
#import <MobileCoreServices/MobileCoreServices.h>
#else
#import <CoreServices/CoreServices.h>
#endif
NSString * const AFURLRequestSerializationErrorDomain = @"com.alamofire.error.serialization.request";
NSString * const AFNetworkingOperationFailingURLRequestErrorKey = @"com.alamofire.serialization.request.error.response";
typedef NSString * (^AFQueryStringSerializationBlock)(NSURLRequest *request, NSDictionary *parameters, NSError *__autoreleasing *error);
@@ -162,7 +169,20 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
#pragma mark -
static NSArray * AFHTTPRequestSerializerObservedKeyPaths() {
static NSArray *_AFHTTPRequestSerializerObservedKeyPaths = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_AFHTTPRequestSerializerObservedKeyPaths = @[NSStringFromSelector(@selector(allowsCellularAccess)), NSStringFromSelector(@selector(cachePolicy)), NSStringFromSelector(@selector(HTTPShouldHandleCookies)), NSStringFromSelector(@selector(HTTPShouldUsePipelining)), NSStringFromSelector(@selector(networkServiceType)), NSStringFromSelector(@selector(timeoutInterval))];
});
return _AFHTTPRequestSerializerObservedKeyPaths;
}
static void *AFHTTPRequestSerializerObserverContext = &AFHTTPRequestSerializerObserverContext;
@interface AFHTTPRequestSerializer ()
@property (readwrite, nonatomic, strong) NSMutableSet *mutableObservedChangedKeyPaths;
@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableHTTPRequestHeaders;
@property (readwrite, nonatomic, assign) AFHTTPRequestQueryStringSerializationStyle queryStringSerializationStyle;
@property (readwrite, nonatomic, copy) AFQueryStringSerializationBlock queryStringSerialization;
@@ -181,12 +201,6 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
}
self.stringEncoding = NSUTF8StringEncoding;
self.allowsCellularAccess = YES;
self.cachePolicy = NSURLRequestUseProtocolCachePolicy;
self.HTTPShouldHandleCookies = YES;
self.HTTPShouldUsePipelining = NO;
self.networkServiceType = NSURLNetworkServiceTypeDefault;
self.timeoutInterval = 60;
self.mutableHTTPRequestHeaders = [NSMutableDictionary dictionary];
@@ -204,7 +218,7 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
#pragma clang diagnostic ignored "-Wgnu"
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
// User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], (__bridge id)CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), kCFBundleVersionKey) ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] ? [[UIScreen mainScreen] scale] : 1.0f)];
userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], (__bridge id)CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), kCFBundleVersionKey) ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]];
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]];
#endif
@@ -222,20 +236,39 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
// HTTP Method Definitions; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
self.HTTPMethodsEncodingParametersInURI = [NSSet setWithObjects:@"GET", @"HEAD", @"DELETE", nil];
self.mutableObservedChangedKeyPaths = [NSMutableSet set];
for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
[self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:AFHTTPRequestSerializerObserverContext];
}
return self;
}
- (void)dealloc {
for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
[self removeObserver:self forKeyPath:keyPath context:AFHTTPRequestSerializerObserverContext];
}
}
#pragma mark -
- (NSDictionary *)HTTPRequestHeaders {
return [NSDictionary dictionaryWithDictionary:self.mutableHTTPRequestHeaders];
}
- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field {
- (void)setValue:(NSString *)value
forHTTPHeaderField:(NSString *)field
{
[self.mutableHTTPRequestHeaders setValue:value forKey:field];
}
- (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username password:(NSString *)password {
- (NSString *)valueForHTTPHeaderField:(NSString *)field {
return [self.mutableHTTPRequestHeaders valueForKey:field];
}
- (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username
password:(NSString *)password
{
NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", username, password];
[self setValue:[NSString stringWithFormat:@"Basic %@", AFBase64EncodedStringFromString(basicAuthCredentials)] forHTTPHeaderField:@"Authorization"];
}
@@ -282,12 +315,12 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];
mutableRequest.HTTPMethod = method;
mutableRequest.allowsCellularAccess = self.allowsCellularAccess;
mutableRequest.cachePolicy = self.cachePolicy;
mutableRequest.HTTPShouldHandleCookies = self.HTTPShouldHandleCookies;
mutableRequest.HTTPShouldUsePipelining = self.HTTPShouldUsePipelining;
mutableRequest.networkServiceType = self.networkServiceType;
mutableRequest.timeoutInterval = self.timeoutInterval;
for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {
[mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];
}
}
mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];
@@ -341,8 +374,7 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
- (NSMutableURLRequest *)requestWithMultipartFormRequest:(NSURLRequest *)request
writingStreamContentsToFile:(NSURL *)fileURL
completionHandler:(void (^)(NSError *error))handler;
completionHandler:(void (^)(NSError *error))handler
{
if (!request.HTTPBodyStream) {
return [request mutableCopy];
@@ -413,33 +445,61 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
}
}];
if (!parameters) {
return mutableRequest;
}
if (parameters) {
NSString *query = nil;
if (self.queryStringSerialization) {
NSError *serializationError;
query = self.queryStringSerialization(request, parameters, &serializationError);
NSString *query = nil;
if (self.queryStringSerialization) {
query = self.queryStringSerialization(request, parameters, error);
} else {
switch (self.queryStringSerializationStyle) {
case AFHTTPRequestQueryStringDefaultStyle:
query = AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding);
break;
if (serializationError) {
if (error) {
*error = serializationError;
}
return nil;
}
} else {
switch (self.queryStringSerializationStyle) {
case AFHTTPRequestQueryStringDefaultStyle:
query = AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding);
break;
}
}
}
if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]];
} else {
NSString *charset = (__bridge NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(self.stringEncoding));
[mutableRequest setValue:[NSString stringWithFormat:@"application/x-www-form-urlencoded; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
[mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];
if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]];
} else {
if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
[mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
}
[mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];
}
}
return mutableRequest;
}
#pragma mark - NSCoding
#pragma mark - NSKeyValueObserving
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(__unused id)object
change:(NSDictionary *)change
context:(void *)context
{
if (context == AFHTTPRequestSerializerObserverContext) {
if ([change[NSKeyValueChangeNewKey] isEqual:[NSNull null]]) {
[self.mutableObservedChangedKeyPaths removeObject:keyPath];
} else {
[self.mutableObservedChangedKeyPaths addObject:keyPath];
}
}
}
#pragma mark - NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [self init];
@@ -447,8 +507,8 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
return nil;
}
self.mutableHTTPRequestHeaders = [decoder decodeObjectForKey:NSStringFromSelector(@selector(mutableHTTPRequestHeaders))];
self.queryStringSerializationStyle = (AFHTTPRequestQueryStringSerializationStyle)[decoder decodeIntegerForKey:NSStringFromSelector(@selector(queryStringSerializationStyle))];
self.mutableHTTPRequestHeaders = [[decoder decodeObjectOfClass:[NSDictionary class] forKey:NSStringFromSelector(@selector(mutableHTTPRequestHeaders))] mutableCopy];
self.queryStringSerializationStyle = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(queryStringSerializationStyle))] unsignedIntegerValue];
return self;
}
@@ -514,14 +574,14 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
@property (nonatomic, strong) NSDictionary *headers;
@property (nonatomic, copy) NSString *boundary;
@property (nonatomic, strong) id body;
@property (nonatomic, assign) NSUInteger bodyContentLength;
@property (nonatomic, assign) unsigned long long bodyContentLength;
@property (nonatomic, strong) NSInputStream *inputStream;
@property (nonatomic, assign) BOOL hasInitialBoundary;
@property (nonatomic, assign) BOOL hasFinalBoundary;
@property (readonly, nonatomic, assign, getter = hasBytesAvailable) BOOL bytesAvailable;
@property (readonly, nonatomic, assign) NSUInteger contentLength;
@property (readonly, nonatomic, assign) unsigned long long contentLength;
- (NSInteger)read:(uint8_t *)buffer
maxLength:(NSUInteger)length;
@@ -531,8 +591,8 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
@property (nonatomic, assign) NSUInteger numberOfBytesInPacket;
@property (nonatomic, assign) NSTimeInterval delay;
@property (nonatomic, strong) NSInputStream *inputStream;
@property (nonatomic, readonly, assign) NSUInteger contentLength;
@property (nonatomic, readonly, assign, getter = isEmpty) BOOL empty;
@property (readonly, nonatomic, assign) unsigned long long contentLength;
@property (readonly, nonatomic, assign, getter = isEmpty) BOOL empty;
- (id)initWithStringEncoding:(NSStringEncoding)encoding;
- (void)setInitialAndFinalBoundaries;
@@ -591,16 +651,16 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
NSParameterAssert(mimeType);
if (![fileURL isFileURL]) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedStringFromTable(@"Expected URL to be a file URL", @"AFNetworking", nil) forKey:NSLocalizedFailureReasonErrorKey];
NSDictionary *userInfo = @{NSLocalizedFailureReasonErrorKey: NSLocalizedStringFromTable(@"Expected URL to be a file URL", @"AFNetworking", nil)};
if (error) {
*error = [[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadURL userInfo:userInfo];
*error = [[NSError alloc] initWithDomain:AFURLRequestSerializationErrorDomain code:NSURLErrorBadURL userInfo:userInfo];
}
return NO;
} else if ([fileURL checkResourceIsReachableAndReturnError:error] == NO) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedStringFromTable(@"File URL not reachable.", @"AFNetworking", nil) forKey:NSLocalizedFailureReasonErrorKey];
NSDictionary *userInfo = @{NSLocalizedFailureReasonErrorKey: NSLocalizedStringFromTable(@"File URL not reachable.", @"AFNetworking", nil)};
if (error) {
*error = [[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadURL userInfo:userInfo];
*error = [[NSError alloc] initWithDomain:AFURLRequestSerializationErrorDomain code:NSURLErrorBadURL userInfo:userInfo];
}
return NO;
@@ -620,7 +680,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
bodyPart.headers = mutableHeaders;
bodyPart.boundary = self.boundary;
bodyPart.body = fileURL;
bodyPart.bodyContentLength = [[fileAttributes objectForKey:NSFileSize] unsignedIntegerValue];
bodyPart.bodyContentLength = [[fileAttributes objectForKey:NSFileSize] unsignedLongLongValue];
[self.bodyStream appendHTTPBodyPart:bodyPart];
return YES;
@@ -629,7 +689,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
- (void)appendPartWithInputStream:(NSInputStream *)inputStream
name:(NSString *)name
fileName:(NSString *)fileName
length:(NSUInteger)length
length:(int64_t)length
mimeType:(NSString *)mimeType
{
NSParameterAssert(name);
@@ -640,13 +700,13 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
[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.boundary = self.boundary;
bodyPart.body = inputStream;
bodyPart.bodyContentLength = length;
bodyPart.bodyContentLength = (unsigned long long)length;
[self.bodyStream appendHTTPBodyPart:bodyPart];
}
@@ -710,7 +770,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
[self.request setHTTPBodyStream:self.bodyStream];
[self.request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", self.boundary] forHTTPHeaderField:@"Content-Type"];
[self.request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)[self.bodyStream contentLength]] forHTTPHeaderField:@"Content-Length"];
[self.request setValue:[NSString stringWithFormat:@"%llu", [self.bodyStream contentLength]] forHTTPHeaderField:@"Content-Length"];
return self.request;
}
@@ -719,9 +779,12 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
#pragma mark -
@interface NSStream ()
@property (readwrite) NSStreamStatus streamStatus;
@property (readwrite, copy) NSError *streamError;
@end
@interface AFMultipartBodyStream () <NSCopying>
@property (readwrite, nonatomic, assign) NSStreamStatus streamStatus;
@property (readwrite, nonatomic, strong) NSError *streamError;
@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
@property (readwrite, nonatomic, strong) NSMutableArray *HTTPBodyParts;
@property (readwrite, nonatomic, strong) NSEnumerator *HTTPBodyPartEnumerator;
@@ -731,6 +794,14 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
@end
@implementation AFMultipartBodyStream
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wimplicit-atomic-properties"
#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1100)
@synthesize delegate;
#endif
@synthesize streamStatus;
@synthesize streamError;
#pragma clang diagnostic pop
- (id)initWithStringEncoding:(NSStringEncoding)encoding {
self = [super init];
@@ -848,8 +919,8 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
forMode:(__unused NSString *)mode
{}
- (NSUInteger)contentLength {
NSUInteger length = 0;
- (unsigned long long)contentLength {
unsigned long long length = 0;
for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
length += [bodyPart contentLength];
}
@@ -901,7 +972,7 @@ typedef enum {
@interface AFHTTPBodyPart () <NSCopying> {
AFHTTPBodyPartReadPhase _phase;
NSInputStream *_inputStream;
NSUInteger _phaseReadOffset;
unsigned long long _phaseReadOffset;
}
- (BOOL)transitionToNextPhase;
@@ -938,6 +1009,8 @@ typedef enum {
_inputStream = [NSInputStream inputStreamWithURL:self.body];
} else if ([self.body isKindOfClass:[NSInputStream class]]) {
_inputStream = self.body;
} else {
_inputStream = [NSInputStream inputStreamWithData:[NSData data]];
}
}
@@ -954,8 +1027,8 @@ typedef enum {
return [NSString stringWithString:headerString];
}
- (NSUInteger)contentLength {
NSUInteger length = 0;
- (unsigned long long)contentLength {
unsigned long long length = 0;
NSData *encapsulationBoundaryData = [([self hasInitialBoundary] ? AFMultipartFormInitialBoundary(self.boundary) : AFMultipartFormEncapsulationBoundary(self.boundary)) dataUsingEncoding:self.stringEncoding];
length += [encapsulationBoundaryData length];
@@ -1039,13 +1112,13 @@ typedef enum {
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
NSRange range = NSMakeRange(_phaseReadOffset, MIN([data length] - _phaseReadOffset, length));
NSRange range = NSMakeRange((NSUInteger)_phaseReadOffset, MIN([data length] - ((NSUInteger)_phaseReadOffset), length));
[data getBytes:buffer range:range];
#pragma clang diagnostic pop
_phaseReadOffset += range.length;
if (_phaseReadOffset >= [data length]) {
if (((NSUInteger)_phaseReadOffset) >= [data length]) {
[self transitionToNextPhase];
}
@@ -1093,6 +1166,7 @@ typedef enum {
bodyPart.headers = self.headers;
bodyPart.bodyContentLength = self.bodyContentLength;
bodyPart.body = self.body;
bodyPart.boundary = self.boundary;
return bodyPart;
}
@@ -1104,7 +1178,7 @@ typedef enum {
@implementation AFJSONRequestSerializer
+ (instancetype)serializer {
return [self serializerWithWritingOptions:0];
return [self serializerWithWritingOptions:(NSJSONWritingOptions)0];
}
+ (instancetype)serializerWithWritingOptions:(NSJSONWritingOptions)writingOptions
@@ -1135,19 +1209,19 @@ typedef enum {
}
}];
if (!parameters) {
return mutableRequest;
if (parameters) {
if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
NSString *charset = (__bridge NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
[mutableRequest setValue:[NSString stringWithFormat:@"application/json; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
}
[mutableRequest setHTTPBody:[NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error]];
}
NSString *charset = (__bridge NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
[mutableRequest setValue:[NSString stringWithFormat:@"application/json; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
[mutableRequest setHTTPBody:[NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error]];
return mutableRequest;
}
#pragma mark - NSCoding
#pragma mark - NSSecureCoding
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
@@ -1155,7 +1229,7 @@ typedef enum {
return nil;
}
self.writingOptions = (NSJSONWritingOptions)[decoder decodeIntegerForKey:NSStringFromSelector(@selector(writingOptions))];
self.writingOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(writingOptions))] unsignedIntegerValue];
return self;
}
@@ -1169,7 +1243,7 @@ typedef enum {
#pragma mark - NSCopying
- (id)copyWithZone:(NSZone *)zone {
AFJSONRequestSerializer *serializer = [[[self class] allocWithZone:zone] init];
AFJSONRequestSerializer *serializer = [super copyWithZone:zone];
serializer.writingOptions = self.writingOptions;
return serializer;
@@ -1215,15 +1289,19 @@ typedef enum {
}
}];
NSString *charset = (__bridge NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
if (parameters) {
if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
NSString *charset = (__bridge NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
[mutableRequest setValue:[NSString stringWithFormat:@"application/x-plist; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
}
[mutableRequest setValue:[NSString stringWithFormat:@"application/x-plist; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
[mutableRequest setHTTPBody:[NSPropertyListSerialization dataWithPropertyList:parameters format:self.format options:self.writeOptions error:error]];
[mutableRequest setHTTPBody:[NSPropertyListSerialization dataWithPropertyList:parameters format:self.format options:self.writeOptions error:error]];
}
return mutableRequest;
}
#pragma mark - NSCoding
#pragma mark - NSSecureCoding
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
@@ -1231,8 +1309,8 @@ typedef enum {
return nil;
}
self.format = (NSPropertyListFormat)[decoder decodeIntegerForKey:NSStringFromSelector(@selector(format))];
self.writeOptions = (NSPropertyListWriteOptions)[decoder decodeIntegerForKey:NSStringFromSelector(@selector(writeOptions))];
self.format = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue];
self.writeOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(writeOptions))] unsignedIntegerValue];
return self;
}
@@ -1241,13 +1319,13 @@ typedef enum {
[super encodeWithCoder:coder];
[coder encodeInteger:self.format forKey:NSStringFromSelector(@selector(format))];
[coder encodeInteger:(NSInteger)self.writeOptions forKey:NSStringFromSelector(@selector(writeOptions))];
[coder encodeObject:@(self.writeOptions) forKey:NSStringFromSelector(@selector(writeOptions))];
}
#pragma mark - NSCopying
- (id)copyWithZone:(NSZone *)zone {
AFPropertyListRequestSerializer *serializer = [[[self class] allocWithZone:zone] init];
AFPropertyListRequestSerializer *serializer = [super copyWithZone:zone];
serializer.format = self.format;
serializer.writeOptions = self.writeOptions;
+50 -5
View File
@@ -1,6 +1,6 @@
// AFSerialization.h
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -28,7 +28,7 @@
For example, a JSON response serializer may check for an acceptable status code (`2XX` range) and content type (`application/json`), decoding a valid JSON response into an object.
*/
@protocol AFURLResponseSerialization <NSObject, NSCoding, NSCopying>
@protocol AFURLResponseSerialization <NSObject, NSSecureCoding, NSCopying>
/**
The response object decoded from the data associated with a specified response.
@@ -73,12 +73,12 @@
See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
*/
@property (nonatomic, strong) NSIndexSet *acceptableStatusCodes;
@property (nonatomic, copy) NSIndexSet *acceptableStatusCodes;
/**
The acceptable MIME types for responses. When non-`nil`, responses with a `Content-Type` with MIME types that do not intersect with the set will result in an error during validation.
*/
@property (nonatomic, strong) NSSet *acceptableContentTypes;
@property (nonatomic, copy) NSSet *acceptableContentTypes;
/**
Validates the specified response and data.
@@ -116,6 +116,11 @@
*/
@property (nonatomic, assign) NSJSONReadingOptions readingOptions;
/**
Whether to remove keys with `NSNull` values from response JSON. Defaults to `NO`.
*/
@property (nonatomic, assign) BOOL removesKeysWithNullValues;
/**
Creates and returns a JSON serializer with specified reading and writing options.
@@ -245,7 +250,7 @@
/**
The component response serializers.
*/
@property (readonly, nonatomic, strong) NSArray *responseSerializers;
@property (readonly, nonatomic, copy) NSArray *responseSerializers;
/**
Creates and returns a compound serializer comprised of the specified response serializers.
@@ -255,3 +260,43 @@
+ (instancetype)compoundSerializerWithResponseSerializers:(NSArray *)responseSerializers;
@end
///----------------
/// @name Constants
///----------------
/**
## Error Domains
The following error domain is predefined.
- `NSString * const AFURLResponseSerializationErrorDomain`
### Constants
`AFURLResponseSerializationErrorDomain`
AFURLResponseSerializer errors. Error codes for `AFURLResponseSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`.
*/
extern NSString * const AFURLResponseSerializationErrorDomain;
/**
## User info dictionary keys
These keys may exist in the user info dictionary, in addition to those defined for NSError.
- `NSString * const AFNetworkingOperationFailingURLResponseErrorKey`
- `NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey`
### Constants
`AFNetworkingOperationFailingURLResponseErrorKey`
The corresponding value is an `NSURLResponse` containing the response of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`.
`AFNetworkingOperationFailingURLResponseDataErrorKey`
The corresponding value is an `NSData` containing the original data of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`.
*/
extern NSString * const AFNetworkingOperationFailingURLResponseErrorKey;
extern NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey;
+101 -48
View File
@@ -1,6 +1,6 @@
// AFSerialization.h
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,15 +22,16 @@
#import "AFURLResponseSerialization.h"
extern NSString * const AFNetworkingErrorDomain;
extern NSString * const AFNetworkingOperationFailingURLResponseErrorKey;
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
#import <UIKit/UIKit.h>
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
#import <Cocoa/Cocoa.h>
#endif
NSString * const AFURLResponseSerializationErrorDomain = @"com.alamofire.error.serialization.response";
NSString * const AFNetworkingOperationFailingURLResponseErrorKey = @"com.alamofire.serialization.response.error.response";
NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey = @"com.alamofire.serialization.response.error.data";
static NSError * AFErrorWithUnderlyingError(NSError *error, NSError *underlyingError) {
if (!error) {
return underlyingError;
@@ -46,16 +47,41 @@ static NSError * AFErrorWithUnderlyingError(NSError *error, NSError *underlyingE
return [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:mutableUserInfo];
}
static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
if (error.code == code) {
static BOOL AFErrorOrUnderlyingErrorHasCodeInDomain(NSError *error, NSInteger code, NSString *domain) {
if ([error.domain isEqualToString:domain] && error.code == code) {
return YES;
} else if (error.userInfo[NSUnderlyingErrorKey]) {
return AFErrorOrUnderlyingErrorHasCode(error.userInfo[NSUnderlyingErrorKey], code);
return AFErrorOrUnderlyingErrorHasCodeInDomain(error.userInfo[NSUnderlyingErrorKey], code, domain);
}
return NO;
}
static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingOptions readingOptions) {
if ([JSONObject isKindOfClass:[NSArray class]]) {
NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:[(NSArray *)JSONObject count]];
for (id value in (NSArray *)JSONObject) {
[mutableArray addObject:AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions)];
}
return (readingOptions & NSJSONReadingMutableContainers) ? mutableArray : [NSArray arrayWithArray:mutableArray];
} else if ([JSONObject isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:JSONObject];
for (id <NSCopying> key in [(NSDictionary *)JSONObject allKeys]) {
id value = [(NSDictionary *)JSONObject objectForKey:key];
if (!value || [value isEqual:[NSNull null]]) {
[mutableDictionary removeObjectForKey:key];
} else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) {
[mutableDictionary setObject:AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions) forKey:key];
}
}
return (readingOptions & NSJSONReadingMutableContainers) ? mutableDictionary : [NSDictionary dictionaryWithDictionary:mutableDictionary];
}
return JSONObject;
}
@implementation AFHTTPResponseSerializer
+ (instancetype)serializer {
@@ -88,26 +114,33 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {
if (self.acceptableContentTypes && ![self.acceptableContentTypes containsObject:[response MIMEType]]) {
if ([data length] > 0) {
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: unacceptable content-type: %@", @"AFNetworking", nil), [response MIMEType]],
NSURLErrorFailingURLErrorKey:[response URL],
AFNetworkingOperationFailingURLResponseErrorKey: response
};
NSMutableDictionary *mutableUserInfo = [@{
NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: unacceptable content-type: %@", @"AFNetworking", nil), [response MIMEType]],
NSURLErrorFailingURLErrorKey:[response URL],
AFNetworkingOperationFailingURLResponseErrorKey: response,
} mutableCopy];
if (data) {
mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
}
validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFNetworkingErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo], validationError);
validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:mutableUserInfo], validationError);
}
responseIsValid = NO;
}
if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode]) {
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%lu)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (unsigned long)response.statusCode],
NSURLErrorFailingURLErrorKey:[response URL],
AFNetworkingOperationFailingURLResponseErrorKey: response
};
NSMutableDictionary *mutableUserInfo = [@{
NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode],
NSURLErrorFailingURLErrorKey:[response URL],
AFNetworkingOperationFailingURLResponseErrorKey: response,
} mutableCopy];
validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo], validationError);
if (data) {
mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
}
validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo], validationError);
responseIsValid = NO;
}
@@ -131,7 +164,11 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
return data;
}
#pragma mark - NSCoding
#pragma mark - NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [self init];
@@ -139,8 +176,8 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
return nil;
}
self.acceptableStatusCodes = [decoder decodeObjectForKey:NSStringFromSelector(@selector(acceptableStatusCodes))];
self.acceptableContentTypes = [decoder decodeObjectForKey:NSStringFromSelector(@selector(acceptableContentTypes))];
self.acceptableStatusCodes = [decoder decodeObjectOfClass:[NSIndexSet class] forKey:NSStringFromSelector(@selector(acceptableStatusCodes))];
self.acceptableContentTypes = [decoder decodeObjectOfClass:[NSIndexSet class] forKey:NSStringFromSelector(@selector(acceptableContentTypes))];
return self;
}
@@ -167,7 +204,7 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
@implementation AFJSONResponseSerializer
+ (instancetype)serializer {
return [self serializerWithReadingOptions:0];
return [self serializerWithReadingOptions:(NSJSONReadingOptions)0];
}
+ (instancetype)serializerWithReadingOptions:(NSJSONReadingOptions)readingOptions {
@@ -195,7 +232,7 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
error:(NSError *__autoreleasing *)error
{
if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
if (AFErrorOrUnderlyingErrorHasCode(*error, NSURLErrorCannotDecodeContentData)) {
if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
return nil;
}
}
@@ -227,23 +264,27 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
}
} else {
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: NSLocalizedStringFromTable(@"Data failed decoding as a UTF-8 string", nil, @"AFNetworking"),
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Could not decode string: %@", nil, @"AFNetworking"), responseString]
NSLocalizedDescriptionKey: NSLocalizedStringFromTable(@"Data failed decoding as a UTF-8 string", @"AFNetworking", nil),
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Could not decode string: %@", @"AFNetworking", nil), responseString]
};
serializationError = [NSError errorWithDomain:AFNetworkingErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo];
serializationError = [NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo];
}
}
}
if (self.removesKeysWithNullValues && responseObject) {
responseObject = AFJSONObjectByRemovingKeysWithNullValues(responseObject, self.readingOptions);
}
if (error) {
*error = AFErrorWithUnderlyingError(serializationError, *error);;
*error = AFErrorWithUnderlyingError(serializationError, *error);
}
return responseObject;
}
#pragma mark - NSCoding
#pragma mark - NSSecureCoding
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
@@ -251,7 +292,8 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
return nil;
}
self.readingOptions = (NSJSONReadingOptions)[decoder decodeIntegerForKey:NSStringFromSelector(@selector(readingOptions))];
self.readingOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(readingOptions))] unsignedIntegerValue];
self.removesKeysWithNullValues = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(removesKeysWithNullValues))] boolValue];
return self;
}
@@ -259,7 +301,8 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeInteger:self.readingOptions forKey:NSStringFromSelector(@selector(readingOptions))];
[coder encodeObject:@(self.readingOptions) forKey:NSStringFromSelector(@selector(readingOptions))];
[coder encodeObject:@(self.removesKeysWithNullValues) forKey:NSStringFromSelector(@selector(removesKeysWithNullValues))];
}
#pragma mark - NSCopying
@@ -267,6 +310,7 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
- (id)copyWithZone:(NSZone *)zone {
AFJSONResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
serializer.readingOptions = self.readingOptions;
serializer.removesKeysWithNullValues = self.removesKeysWithNullValues;
return serializer;
}
@@ -301,7 +345,7 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
error:(NSError *__autoreleasing *)error
{
if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
if (AFErrorOrUnderlyingErrorHasCode(*error, NSURLErrorCannotDecodeContentData)) {
if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
return nil;
}
}
@@ -346,7 +390,7 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
error:(NSError *__autoreleasing *)error
{
if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
if (AFErrorOrUnderlyingErrorHasCode(*error, NSURLErrorCannotDecodeContentData)) {
if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
return nil;
}
}
@@ -361,7 +405,7 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
return document;
}
#pragma mark - NSCoding
#pragma mark - NSSecureCoding
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
@@ -369,7 +413,7 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
return nil;
}
self.options = [decoder decodeIntegerForKey:NSStringFromSelector(@selector(options))];
self.options = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(options))] unsignedIntegerValue];
return self;
}
@@ -377,7 +421,7 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeInteger:self.options forKey:NSStringFromSelector(@selector(options))];
[coder encodeObject:@(self.options) forKey:NSStringFromSelector(@selector(options))];
}
#pragma mark - NSCopying
@@ -429,7 +473,7 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
error:(NSError *__autoreleasing *)error
{
if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
if (AFErrorOrUnderlyingErrorHasCode(*error, NSURLErrorCannotDecodeContentData)) {
if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
return nil;
}
}
@@ -448,7 +492,7 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
return responseObject;
}
#pragma mark - NSCoding
#pragma mark - NSSecureCoding
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
@@ -456,8 +500,8 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
return nil;
}
self.format = (NSPropertyListFormat)[decoder decodeIntegerForKey:NSStringFromSelector(@selector(format))];
self.readOptions = (NSPropertyListReadOptions)[decoder decodeIntegerForKey:NSStringFromSelector(@selector(readOptions))];
self.format = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue];
self.readOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(readOptions))] unsignedIntegerValue];
return self;
}
@@ -465,8 +509,8 @@ static BOOL AFErrorOrUnderlyingErrorHasCode(NSError *error, NSInteger code) {
- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
[coder encodeInteger:self.format forKey:NSStringFromSelector(@selector(format))];
[coder encodeInteger:(NSInteger)self.readOptions forKey:NSStringFromSelector(@selector(readOptions))];
[coder encodeObject:@(self.format) forKey:NSStringFromSelector(@selector(format))];
[coder encodeObject:@(self.readOptions) forKey:NSStringFromSelector(@selector(readOptions))];
}
#pragma mark - NSCopying
@@ -547,6 +591,8 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r
if (colorSpaceModel == kCGColorSpaceModelRGB) {
uint32_t alpha = (bitmapInfo & kCGBitmapAlphaInfoMask);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wassign-enum"
if (alpha == kCGImageAlphaNone) {
bitmapInfo &= ~kCGBitmapAlphaInfoMask;
bitmapInfo |= kCGImageAlphaNoneSkipFirst;
@@ -554,6 +600,7 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r
bitmapInfo &= ~kCGBitmapAlphaInfoMask;
bitmapInfo |= kCGImageAlphaPremultipliedFirst;
}
#pragma clang diagnostic pop
}
CGContextRef context = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo);
@@ -606,7 +653,7 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r
error:(NSError *__autoreleasing *)error
{
if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
if (AFErrorOrUnderlyingErrorHasCode(*error, NSURLErrorCannotDecodeContentData)) {
if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
return nil;
}
}
@@ -629,7 +676,7 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r
return nil;
}
#pragma mark - NSCoding
#pragma mark - NSSecureCoding
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
@@ -638,7 +685,13 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r
}
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
self.imageScale = [[decoder decodeObjectForKey:NSStringFromSelector(@selector(imageScale))] floatValue];
NSNumber *imageScale = [decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(imageScale))];
#if CGFLOAT_IS_DOUBLE
self.imageScale = [imageScale doubleValue];
#else
self.imageScale = [imageScale floatValue];
#endif
self.automaticallyInflatesResponseImage = [decoder decodeBoolForKey:NSStringFromSelector(@selector(automaticallyInflatesResponseImage))];
#endif
@@ -672,7 +725,7 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r
#pragma mark -
@interface AFCompoundResponseSerializer ()
@property (readwrite, nonatomic, strong) NSArray *responseSerializers;
@property (readwrite, nonatomic, copy) NSArray *responseSerializers;
@end
@implementation AFCompoundResponseSerializer
@@ -709,7 +762,7 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r
return [super responseObjectForResponse:response data:data error:error];
}
#pragma mark - NSCoding
#pragma mark - NSSecureCoding
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
@@ -717,7 +770,7 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r
return nil;
}
self.responseSerializers = [decoder decodeObjectForKey:NSStringFromSelector(@selector(responseSerializers))];
self.responseSerializers = [decoder decodeObjectOfClass:[NSArray class] forKey:NSStringFromSelector(@selector(responseSerializers))];
return self;
}
+44 -5
View File
@@ -1,6 +1,6 @@
// AFURLSessionManager.h
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -42,6 +42,7 @@
- `URLSession:didBecomeInvalidWithError:`
- `URLSession:didReceiveChallenge:completionHandler:`
- `URLSessionDidFinishEventsForBackgroundURLSession:`
### `NSURLSessionTaskDelegate`
@@ -56,7 +57,6 @@
- `URLSession:dataTask:didBecomeDownloadTask:`
- `URLSession:dataTask:didReceiveData:`
- `URLSession:dataTask:willCacheResponse:completionHandler:`
- `URLSessionDidFinishEventsForBackgroundURLSession:`
### `NSURLSessionDownloadDelegate`
@@ -82,7 +82,7 @@
#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090)
@interface AFURLSessionManager : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate, NSCoding, NSCopying>
@interface AFURLSessionManager : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate, NSSecureCoding, NSCopying>
/**
The managed session.
@@ -143,9 +143,9 @@
*/
@property (readonly, nonatomic, strong) NSArray *downloadTasks;
///---------------------------------
///-------------------------------
/// @name Managing Callback Queues
///---------------------------------
///-------------------------------
/**
The dispatch queue for `completionBlock`. If `NULL` (default), the main queue is used.
@@ -157,6 +157,19 @@
*/
@property (nonatomic, strong) dispatch_group_t completionGroup;
///---------------------------------
/// @name Working Around System Bugs
///---------------------------------
/**
Whether to attempt to retry creation of upload tasks for background sessions when initial call returns `nil`. `NO` by default.
@bug As of iOS 7.0, there is a bug where upload tasks created for background tasks are sometimes `nil`. As a workaround, if this property is `YES`, AFNetworking will follow Apple's recommendation to try creating the task again.
@see https://github.com/AFNetworking/AFNetworking/issues/1675
*/
@property (nonatomic, assign) BOOL attemptsToRecreateUploadTasksForBackgroundSessions;
///---------------------
/// @name Initialization
///---------------------
@@ -201,6 +214,8 @@
@param fileURL A URL to the local file to be uploaded.
@param progress A progress object monitoring the current upload progress.
@param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any.
@see `attemptsToRecreateUploadTasksForBackgroundSessions`
*/
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
fromFile:(NSURL *)fileURL
@@ -242,6 +257,8 @@
@param progress A progress object monitoring the current download progress.
@param destination A block object to be executed in order to determine the destination of the downloaded file. This block takes two arguments, the target path & the server response, and returns the desired file URL of the resulting download. The temporary file used during the download will be automatically deleted after being moved to the returned URL.
@param completionHandler A block to be executed when a task finishes. This block has no return value and takes three arguments: the server response, the path of the downloaded file, and the error describing the network or parsing error that occurred, if any.
@warning If using a background `NSURLSessionConfiguration` on iOS, these blocks will be lost when the app is terminated. Background sessions may prefer to use `-setDownloadTaskDidFinishDownloadingBlock:` to specify the URL for saving the downloaded file, rather than the destination block of this method.
*/
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
progress:(NSProgress * __autoreleasing *)progress
@@ -261,6 +278,28 @@
destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler;
///---------------------------------
/// @name Getting Progress for Tasks
///---------------------------------
/**
Returns the upload progress of the specified task.
@param uploadTask The session upload task. Must not be `nil`.
@return An `NSProgress` object reporting the upload progress of a task, or `nil` if the progress is unavailable.
*/
- (NSProgress *)uploadProgressForTask:(NSURLSessionUploadTask *)uploadTask;
/**
Returns the download progress of the specified task.
@param downloadTask The session download task. Must not be `nil`.
@return An `NSProgress` object reporting the download progress of a task, or `nil` if the progress is unavailable.
*/
- (NSProgress *)downloadProgressForTask:(NSURLSessionDownloadTask *)downloadTask;
///-----------------------------------------
/// @name Setting Session Delegate Callbacks
///-----------------------------------------
+274 -174
View File
@@ -1,6 +1,6 @@
// AFURLSessionManager.m
//
// Copyright (c) 2013 AFNetworking (http://afnetworking.com)
// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -24,6 +24,16 @@
#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090)
static dispatch_queue_t url_session_manager_creation_queue() {
static dispatch_queue_t af_url_session_manager_creation_queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
af_url_session_manager_creation_queue = dispatch_queue_create("com.alamofire.networking.session.manager.creation", DISPATCH_QUEUE_SERIAL);
});
return af_url_session_manager_creation_queue;
}
static dispatch_queue_t url_session_manager_processing_queue() {
static dispatch_queue_t af_url_session_manager_processing_queue;
static dispatch_once_t onceToken;
@@ -67,6 +77,8 @@ NSString * const AFNetworkingTaskDidFinishAssetPathKey = @"com.alamofire.network
static NSString * const AFURLSessionManagerLockName = @"com.alamofire.networking.session.manager.lock";
static NSUInteger const AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask = 3;
static void * AFTaskStateChangedContext = &AFTaskStateChangedContext;
typedef void (^AFURLSessionDidBecomeInvalidBlock)(NSURLSession *session, NSError *error);
@@ -74,6 +86,7 @@ typedef NSURLSessionAuthChallengeDisposition (^AFURLSessionDidReceiveAuthenticat
typedef NSURLRequest * (^AFURLSessionTaskWillPerformHTTPRedirectionBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request);
typedef NSURLSessionAuthChallengeDisposition (^AFURLSessionTaskDidReceiveAuthenticationChallengeBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential);
typedef void (^AFURLSessionDidFinishEventsForBackgroundURLSessionBlock)(NSURLSession *session);
typedef NSInputStream * (^AFURLSessionTaskNeedNewBodyStreamBlock)(NSURLSession *session, NSURLSessionTask *task);
typedef void (^AFURLSessionTaskDidSendBodyDataBlock)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend);
@@ -83,7 +96,6 @@ typedef NSURLSessionResponseDisposition (^AFURLSessionDataTaskDidReceiveResponse
typedef void (^AFURLSessionDataTaskDidBecomeDownloadTaskBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask);
typedef void (^AFURLSessionDataTaskDidReceiveDataBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data);
typedef NSCachedURLResponse * (^AFURLSessionDataTaskWillCacheResponseBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse);
typedef void (^AFURLSessionDidFinishEventsForBackgroundURLSessionBlock)(NSURLSession *session);
typedef NSURL * (^AFURLSessionDownloadTaskDidFinishDownloadingBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location);
typedef void (^AFURLSessionDownloadTaskDidWriteDataBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite);
@@ -95,32 +107,15 @@ typedef void (^AFURLSessionTaskCompletionHandler)(NSURLResponse *response, id re
@interface AFURLSessionManagerTaskDelegate : NSObject <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>
@property (nonatomic, weak) AFURLSessionManager *manager;
@property (nonatomic, strong) id <AFURLResponseSerialization> responseSerializer;
@property (nonatomic, strong) NSMutableData *mutableData;
@property (nonatomic, strong) NSProgress *uploadProgress;
@property (nonatomic, strong) NSProgress *downloadProgress;
@property (nonatomic, strong) NSProgress *progress;
@property (nonatomic, copy) NSURL *downloadFileURL;
@property (nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
@property (nonatomic, copy) AFURLSessionTaskCompletionHandler completionHandler;
+ (instancetype)delegateForManager:(AFURLSessionManager *)manager
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler;
@end
@implementation AFURLSessionManagerTaskDelegate
+ (instancetype)delegateForManager:(AFURLSessionManager *)manager
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
AFURLSessionManagerTaskDelegate *delegate = [[self alloc] init];
delegate.manager = manager;
delegate.responseSerializer = manager.responseSerializer;
delegate.completionHandler = completionHandler;
return delegate;
}
- (instancetype)init {
self = [super init];
if (!self) {
@@ -129,8 +124,7 @@ typedef void (^AFURLSessionTaskCompletionHandler)(NSURLResponse *response, id re
self.mutableData = [NSMutableData data];
self.uploadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil];
self.downloadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil];
self.progress = [NSProgress progressWithTotalUnitCount:0];
return self;
}
@@ -143,15 +137,8 @@ typedef void (^AFURLSessionTaskCompletionHandler)(NSURLResponse *response, id re
totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
int64_t totalUnitCount = totalBytesExpectedToSend;
if(totalUnitCount == NSURLSessionTransferSizeUnknown) {
NSString *contentLength = [task.originalRequest valueForHTTPHeaderField:@"Content-Length"];
if(contentLength) {
totalUnitCount = (int64_t) [contentLength longLongValue];
}
}
self.uploadProgress.totalUnitCount = totalUnitCount;
self.uploadProgress.completedUnitCount = totalBytesSent;
self.progress.totalUnitCount = totalBytesExpectedToSend;
self.progress.completedUnitCount = totalBytesSent;
}
- (void)URLSession:(__unused NSURLSession *)session
@@ -165,7 +152,7 @@ didCompleteWithError:(NSError *)error
__block id responseObject = nil;
__block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = self.responseSerializer;
userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;
if (self.downloadFileURL) {
userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
@@ -188,7 +175,7 @@ didCompleteWithError:(NSError *)error
} else {
dispatch_async(url_session_manager_processing_queue(), ^{
NSError *serializationError = nil;
responseObject = [self.responseSerializer responseObjectForResponse:task.response data:[NSData dataWithData:self.mutableData] error:&serializationError];
responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:[NSData dataWithData:self.mutableData] error:&serializationError];
if (self.downloadFileURL) {
responseObject = self.downloadFileURL;
@@ -223,8 +210,6 @@ didCompleteWithError:(NSError *)error
didReceiveData:(NSData *)data
{
[self.mutableData appendData:data];
self.downloadProgress.completedUnitCount += (int64_t)[data length];
}
#pragma mark - NSURLSessionDownloadTaskDelegate
@@ -254,16 +239,16 @@ didFinishDownloadingToURL:(NSURL *)location
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
self.downloadProgress.totalUnitCount = totalBytesExpectedToWrite;
self.downloadProgress.completedUnitCount = totalBytesWritten;
self.progress.totalUnitCount = totalBytesExpectedToWrite;
self.progress.completedUnitCount = totalBytesWritten;
}
- (void)URLSession:(__unused NSURLSession *)session
downloadTask:(__unused NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes {
self.downloadProgress.totalUnitCount = expectedTotalBytes;
self.downloadProgress.completedUnitCount = fileOffset;
self.progress.totalUnitCount = expectedTotalBytes;
self.progress.completedUnitCount = fileOffset;
}
@end
@@ -278,6 +263,7 @@ expectedTotalBytes:(int64_t)expectedTotalBytes {
@property (readwrite, nonatomic, strong) NSLock *lock;
@property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid;
@property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge;
@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession;
@property (readwrite, nonatomic, copy) AFURLSessionTaskWillPerformHTTPRedirectionBlock taskWillPerformHTTPRedirection;
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidReceiveAuthenticationChallengeBlock taskDidReceiveAuthenticationChallenge;
@property (readwrite, nonatomic, copy) AFURLSessionTaskNeedNewBodyStreamBlock taskNeedNewBodyStream;
@@ -287,7 +273,6 @@ expectedTotalBytes:(int64_t)expectedTotalBytes {
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidBecomeDownloadTaskBlock dataTaskDidBecomeDownloadTask;
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveDataBlock dataTaskDidReceiveData;
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskWillCacheResponseBlock dataTaskWillCacheResponse;
@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession;
@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidWriteDataBlock downloadTaskDidWriteData;
@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidResumeBlock downloadTaskDidResume;
@@ -309,30 +294,41 @@ expectedTotalBytes:(int64_t)expectedTotalBytes {
configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
}
self.operationQueue = [[NSOperationQueue alloc] init];
self.operationQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount;
self.responseSerializer = [AFJSONResponseSerializer serializer];
self.sessionConfiguration = configuration;
self.operationQueue = [[NSOperationQueue alloc] init];
self.operationQueue.maxConcurrentOperationCount = 1;
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];
self.responseSerializer = [AFJSONResponseSerializer serializer];
self.securityPolicy = [AFSecurityPolicy defaultPolicy];
self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];
self.lock = [[NSLock alloc] init];
self.lock.name = AFURLSessionManagerLockName;
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
for (NSURLSessionDataTask *task in dataTasks) {
[self addDelegateForDataTask:task completionHandler:nil];
}
for (NSURLSessionUploadTask *uploadTask in uploadTasks) {
[self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil];
}
for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
[self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil];
}
}];
return self;
}
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, self.session, self.operationQueue];
}
#pragma mark -
- (AFURLSessionManagerTaskDelegate *)delegateForTask:(NSURLSessionTask *)task {
@@ -352,17 +348,80 @@ expectedTotalBytes:(int64_t)expectedTotalBytes {
NSParameterAssert(task);
NSParameterAssert(delegate);
[task addObserver:self forKeyPath:NSStringFromSelector(@selector(state)) options:(NSKeyValueObservingOptions)(NSKeyValueObservingOptionOld |NSKeyValueObservingOptionNew) context:AFTaskStateChangedContext];
[self.lock lock];
[task addObserver:self forKeyPath:NSStringFromSelector(@selector(state)) options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:AFTaskStateChangedContext];
self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
[self.lock unlock];
}
- (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
delegate.manager = self;
delegate.completionHandler = completionHandler;
[self setDelegate:delegate forTask:dataTask];
}
- (void)addDelegateForUploadTask:(NSURLSessionUploadTask *)uploadTask
progress:(NSProgress * __autoreleasing *)progress
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
delegate.manager = self;
delegate.completionHandler = completionHandler;
int64_t totalUnitCount = uploadTask.countOfBytesExpectedToSend;
if(totalUnitCount == NSURLSessionTransferSizeUnknown) {
NSString *contentLength = [uploadTask.originalRequest valueForHTTPHeaderField:@"Content-Length"];
if(contentLength) {
totalUnitCount = (int64_t) [contentLength longLongValue];
}
}
delegate.progress = [NSProgress progressWithTotalUnitCount:totalUnitCount];
delegate.progress.pausingHandler = ^{
[uploadTask suspend];
};
delegate.progress.cancellationHandler = ^{
[uploadTask cancel];
};
if (progress) {
*progress = delegate.progress;
}
[self setDelegate:delegate forTask:uploadTask];
}
- (void)addDelegateForDownloadTask:(NSURLSessionDownloadTask *)downloadTask
progress:(NSProgress * __autoreleasing *)progress
destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
{
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
delegate.manager = self;
delegate.completionHandler = completionHandler;
if (destination) {
delegate.downloadTaskDidFinishDownloading = ^NSURL * (NSURLSession * __unused session, NSURLSessionDownloadTask *task, NSURL *location) {
return destination(location, task.response);
};
}
if (progress) {
*progress = delegate.progress;
}
[self setDelegate:delegate forTask:downloadTask];
}
- (void)removeDelegateForTask:(NSURLSessionTask *)task {
NSParameterAssert(task);
[self.lock lock];
[task removeObserver:self forKeyPath:NSStringFromSelector(@selector(state)) context:AFTaskStateChangedContext];
[self.lock lock];
[self.mutableTaskDelegatesKeyedByTaskIdentifier removeObjectForKey:@(task.taskIdentifier)];
[self.lock unlock];
}
@@ -416,11 +475,13 @@ expectedTotalBytes:(int64_t)expectedTotalBytes {
#pragma mark -
- (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks {
if (cancelPendingTasks) {
[self.session invalidateAndCancel];
} else {
[self.session finishTasksAndInvalidate];
}
dispatch_async(dispatch_get_main_queue(), ^{
if (cancelPendingTasks) {
[self.session invalidateAndCancel];
} else {
[self.session finishTasksAndInvalidate];
}
});
}
#pragma mark -
@@ -436,10 +497,12 @@ expectedTotalBytes:(int64_t)expectedTotalBytes {
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request];
__block NSURLSessionDataTask *dataTask = nil;
dispatch_sync(url_session_manager_creation_queue(), ^{
dataTask = [self.session dataTaskWithRequest:request];
});
AFURLSessionManagerTaskDelegate *delegate = [AFURLSessionManagerTaskDelegate delegateForManager:self completionHandler:completionHandler];
[self setDelegate:delegate forTask:dataTask];
[self addDelegateForDataTask:dataTask completionHandler:completionHandler];
return dataTask;
}
@@ -451,9 +514,20 @@ expectedTotalBytes:(int64_t)expectedTotalBytes {
progress:(NSProgress * __autoreleasing *)progress
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL];
__block NSURLSessionUploadTask *uploadTask = nil;
dispatch_sync(url_session_manager_creation_queue(), ^{
uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL];
});
return [self uploadTaskWithTask:uploadTask progress:progress completionHandler:completionHandler];
if (!uploadTask && self.attemptsToRecreateUploadTasksForBackgroundSessions && self.session.configuration.identifier) {
for (NSUInteger attempts = 0; !uploadTask && attempts < AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask; attempts++) {
uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL];
}
}
[self addDelegateForUploadTask:uploadTask progress:progress completionHandler:completionHandler];
return uploadTask;
}
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
@@ -461,50 +535,27 @@ expectedTotalBytes:(int64_t)expectedTotalBytes {
progress:(NSProgress * __autoreleasing *)progress
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromData:bodyData];
__block NSURLSessionUploadTask *uploadTask = nil;
dispatch_sync(url_session_manager_creation_queue(), ^{
uploadTask = [self.session uploadTaskWithRequest:request fromData:bodyData];
});
return [self uploadTaskWithTask:uploadTask progress:progress completionHandler:completionHandler];
[self addDelegateForUploadTask:uploadTask progress:progress completionHandler:completionHandler];
return uploadTask;
}
- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request
progress:(NSProgress * __autoreleasing *)progress
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithStreamedRequest:request];
__block NSURLSessionUploadTask *uploadTask = nil;
dispatch_sync(url_session_manager_creation_queue(), ^{
uploadTask = [self.session uploadTaskWithStreamedRequest:request];
});
return [self uploadTaskWithTask:uploadTask progress:progress completionHandler:completionHandler];
}
[self addDelegateForUploadTask:uploadTask progress:progress completionHandler:completionHandler];
- (NSURLSessionUploadTask *)uploadTaskWithTask:(NSURLSessionUploadTask *)uploadTask
progress:(NSProgress * __autoreleasing *)progress
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
NSParameterAssert(uploadTask);
AFURLSessionManagerTaskDelegate *delegate = [AFURLSessionManagerTaskDelegate delegateForManager:self completionHandler:completionHandler];
int64_t totalUnitCount = uploadTask.countOfBytesExpectedToSend;
if(totalUnitCount == NSURLSessionTransferSizeUnknown) {
NSString *contentLength = [uploadTask.originalRequest valueForHTTPHeaderField:@"Content-Length"];
if(contentLength) {
totalUnitCount = (int64_t) [contentLength longLongValue];
}
}
delegate.uploadProgress = [NSProgress progressWithTotalUnitCount:totalUnitCount];
delegate.uploadProgress.pausingHandler = ^{
[uploadTask suspend];
};
delegate.uploadProgress.cancellationHandler = ^{
[uploadTask cancel];
};
if (progress) {
*progress = delegate.uploadProgress;
}
[self setDelegate:delegate forTask:uploadTask];
return uploadTask;
}
@@ -515,9 +566,14 @@ expectedTotalBytes:(int64_t)expectedTotalBytes {
destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
{
NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request];
__block NSURLSessionDownloadTask *downloadTask = nil;
dispatch_sync(url_session_manager_creation_queue(), ^{
downloadTask = [self.session downloadTaskWithRequest:request];
});
return [self downloadTaskWithTask:downloadTask progress:progress destination:destination completionHandler:completionHandler];
[self addDelegateForDownloadTask:downloadTask progress:progress destination:destination completionHandler:completionHandler];
return downloadTask;
}
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData
@@ -525,38 +581,28 @@ expectedTotalBytes:(int64_t)expectedTotalBytes {
destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
{
NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithResumeData:resumeData];
__block NSURLSessionDownloadTask *downloadTask = nil;
dispatch_sync(url_session_manager_creation_queue(), ^{
downloadTask = [self.session downloadTaskWithResumeData:resumeData];
});
return [self downloadTaskWithTask:downloadTask progress:progress destination:destination completionHandler:completionHandler];
}
- (NSURLSessionDownloadTask *)downloadTaskWithTask:(NSURLSessionDownloadTask *)downloadTask
progress:(NSProgress * __autoreleasing *)progress
destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
{
NSParameterAssert(downloadTask);
AFURLSessionManagerTaskDelegate *delegate = [AFURLSessionManagerTaskDelegate delegateForManager:self completionHandler:completionHandler];
delegate.downloadTaskDidFinishDownloading = ^NSURL * (NSURLSession * __unused session, NSURLSessionDownloadTask *task, NSURL *location) {
if (destination) {
return destination(location, task.response);
}
return location;
};
if (progress) {
*progress = delegate.downloadProgress;
}
[self setDelegate:delegate forTask:downloadTask];
[self addDelegateForDownloadTask:downloadTask progress:progress destination:destination completionHandler:completionHandler];
return downloadTask;
}
#pragma mark -
- (NSProgress *)uploadProgressForTask:(NSURLSessionUploadTask *)uploadTask {
return [[self delegateForTask:uploadTask] progress];
}
- (NSProgress *)downloadProgressForTask:(NSURLSessionDownloadTask *)downloadTask {
return [[self delegateForTask:downloadTask] progress];
}
#pragma mark -
- (void)setSessionDidBecomeInvalidBlock:(void (^)(NSURLSession *session, NSError *error))block {
self.sessionDidBecomeInvalid = block;
}
@@ -565,10 +611,14 @@ expectedTotalBytes:(int64_t)expectedTotalBytes {
self.sessionDidReceiveAuthenticationChallenge = block;
}
- (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block {
self.didFinishEventsForBackgroundURLSession = block;
}
#pragma mark -
- (void)setTaskNeedNewBodyStreamBlock:(NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block {
self.taskNeedNewBodyStream = block;
self.taskNeedNewBodyStream = block;
}
- (void)setTaskWillPerformHTTPRedirectionBlock:(NSURLRequest * (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block {
@@ -605,10 +655,6 @@ expectedTotalBytes:(int64_t)expectedTotalBytes {
self.dataTaskWillCacheResponse = block;
}
- (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block {
self.didFinishEventsForBackgroundURLSession = block;
}
#pragma mark -
- (void)setDownloadTaskDidFinishDownloadingBlock:(NSURL * (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block {
@@ -623,6 +669,62 @@ expectedTotalBytes:(int64_t)expectedTotalBytes {
self.downloadTaskDidResume = block;
}
#pragma mark - NSObject
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, self.session, self.operationQueue];
}
- (BOOL)respondsToSelector:(SEL)selector {
if (selector == @selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:)) {
return self.taskWillPerformHTTPRedirection != nil;
} else if (selector == @selector(URLSession:dataTask:didReceiveResponse:completionHandler:)) {
return self.dataTaskDidReceiveResponse != nil;
} else if (selector == @selector(URLSession:dataTask:willCacheResponse:completionHandler:)) {
return self.dataTaskWillCacheResponse != nil;
} else if (selector == @selector(URLSessionDidFinishEventsForBackgroundURLSession:)) {
return self.didFinishEventsForBackgroundURLSession != nil;
}
return [[self class] instancesRespondToSelector:selector];
}
#pragma mark - NSKeyValueObserving
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if (context == AFTaskStateChangedContext && [keyPath isEqualToString:@"state"]) {
if (change[NSKeyValueChangeOldKey] && change[NSKeyValueChangeNewKey] && [change[NSKeyValueChangeNewKey] isEqual:change[NSKeyValueChangeOldKey]]) {
return;
}
NSString *notificationName = nil;
switch ([(NSURLSessionTask *)object state]) {
case NSURLSessionTaskStateRunning:
notificationName = AFNetworkingTaskDidResumeNotification;
break;
case NSURLSessionTaskStateSuspended:
notificationName = AFNetworkingTaskDidSuspendNotification;
break;
case NSURLSessionTaskStateCompleted:
// AFNetworkingTaskDidFinishNotification posted by task completion handlers
default:
break;
}
if (notificationName) {
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:object];
});
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
#pragma mark - NSURLSessionDelegate
- (void)URLSession:(NSURLSession *)session
@@ -632,7 +734,14 @@ didBecomeInvalidWithError:(NSError *)error
self.sessionDidBecomeInvalid(session, error);
}
[self removeAllDelegates];
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
NSArray *tasks = [@[dataTasks, uploadTasks, downloadTasks] valueForKeyPath:@"@unionOfArrays.self"];
for (NSURLSessionTask *task in tasks) {
[task removeObserver:self forKeyPath:NSStringFromSelector(@selector(state)) context:AFTaskStateChangedContext];
}
[self removeAllDelegates];
}];
[[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDidInvalidateNotification object:session];
}
@@ -738,11 +847,20 @@ didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
int64_t totalUnitCount = totalBytesExpectedToSend;
if(totalUnitCount == NSURLSessionTransferSizeUnknown) {
NSString *contentLength = [task.originalRequest valueForHTTPHeaderField:@"Content-Length"];
if(contentLength) {
totalUnitCount = (int64_t) [contentLength longLongValue];
}
}
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
[delegate URLSession:session task:task didSendBodyData:bytesSent totalBytesSent:totalBytesSent totalBytesExpectedToSend:totalBytesExpectedToSend];
[delegate URLSession:session task:task didSendBodyData:bytesSent totalBytesSent:totalBytesSent totalBytesExpectedToSend:totalUnitCount];
if (self.taskDidSendBodyData) {
self.taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend);
self.taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalUnitCount);
}
}
@@ -756,12 +874,13 @@ didCompleteWithError:(NSError *)error
if (delegate) {
[delegate URLSession:session task:task didCompleteWithError:error];
if (self.taskDidComplete) {
self.taskDidComplete(session, task, error);
}
[self removeDelegateForTask:task];
}
if (self.taskDidComplete) {
self.taskDidComplete(session, task, error);
}
}
#pragma mark - NSURLSessionDataDelegate
@@ -817,7 +936,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
NSCachedURLResponse *cachedResponse = proposedResponse;
if (self.dataTaskWillCacheResponse) {
cachedResponse = self.dataTaskWillCacheResponse(session, dataTask, proposedResponse);
cachedResponse = self.dataTaskWillCacheResponse(session, dataTask, proposedResponse);
}
if (completionHandler) {
@@ -827,7 +946,9 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
if (self.didFinishEventsForBackgroundURLSession) {
self.didFinishEventsForBackgroundURLSession(session);
dispatch_async(dispatch_get_main_queue(), ^{
self.didFinishEventsForBackgroundURLSession(session);
});
}
}
@@ -837,10 +958,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
if (delegate) {
[delegate URLSession:session downloadTask:downloadTask didFinishDownloadingToURL:location];
} else if (self.downloadTaskDidFinishDownloading) {
if (self.downloadTaskDidFinishDownloading) {
NSURL *fileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
if (fileURL) {
NSError *error = nil;
@@ -848,8 +966,15 @@ didFinishDownloadingToURL:(NSURL *)location
if (error) {
[[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:error.userInfo];
}
return;
}
}
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
if (delegate) {
[delegate URLSession:session downloadTask:downloadTask didFinishDownloadingToURL:location];
}
}
- (void)URLSession:(NSURLSession *)session
@@ -871,47 +996,22 @@ totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
[delegate URLSession:session downloadTask:downloadTask didResumeAtOffset:fileOffset expectedTotalBytes:expectedTotalBytes];
if (self.downloadTaskDidResume) {
self.downloadTaskDidResume(session, downloadTask, fileOffset, expectedTotalBytes);
}
}
#pragma mark - NSKeyValueObserving
#pragma mark - NSSecureCoding
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if (context == AFTaskStateChangedContext && [keyPath isEqualToString:@"state"]) {
NSString *notificationName = nil;
switch ([(NSURLSessionTask *)object state]) {
case NSURLSessionTaskStateRunning:
notificationName = AFNetworkingTaskDidResumeNotification;
break;
case NSURLSessionTaskStateSuspended:
notificationName = AFNetworkingTaskDidSuspendNotification;
break;
case NSURLSessionTaskStateCompleted:
// AFNetworkingTaskDidFinishNotification posted by task completion handlers
default:
break;
}
if (notificationName) {
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:object];
});
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
+ (BOOL)supportsSecureCoding {
return YES;
}
#pragma mark - NSCoding
- (id)initWithCoder:(NSCoder *)decoder {
NSURLSessionConfiguration *configuration = [decoder decodeObjectForKey:@"sessionConfiguration"];
NSURLSessionConfiguration *configuration = [decoder decodeObjectOfClass:[NSURLSessionConfiguration class] forKey:@"sessionConfiguration"];
self = [self initWithSessionConfiguration:configuration];
if (!self) {