Merge branch 'experimental-1.0RC1'

This commit is contained in:
Mattt Thompson 2012-04-24 22:00:46 -07:00
commit 948628e11d
11 changed files with 522 additions and 199 deletions

View File

@ -38,7 +38,19 @@ extern NSString * const AFNetworkingReachabilityDidChangeNotification;
#endif
/**
Method used to encode parameters into request body.
Specifies network reachability of the client to its `baseURL` domain.
*/
#ifdef _SYSTEMCONFIGURATION_H
typedef enum {
AFNetworkReachabilityStatusUnknown = -1,
AFNetworkReachabilityStatusNotReachable = 0,
AFNetworkReachabilityStatusReachableViaWWAN = 1,
AFNetworkReachabilityStatusReachableViaWiFi = 2,
} AFNetworkReachabilityStatus;
#endif
/**
Specifies the method used to encode parameters into request body.
*/
typedef enum {
AFFormURLParameterEncoding,
@ -141,6 +153,15 @@ extern NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *paramete
*/
@property (readonly, nonatomic, retain) NSOperationQueue *operationQueue;
/**
The reachability status from the device to the current `baseURL` of the `AFHTTPClient`.
@warning This property requires the `SystemConfiguration` framework. Add it in the active target's "Link Binary With Library" build phase, and add `#import <SystemConfiguration/SystemConfiguration.h>` to the header prefix of the project (Prefix.pch).
*/
#ifdef _SYSTEMCONFIGURATION_H
@property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
#endif
///---------------------------------------------
/// @name Creating and Initializing HTTP Clients
///---------------------------------------------
@ -172,12 +193,12 @@ extern NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *paramete
/**
Sets a callback to be executed when the network availability of the `baseURL` host changes.
@param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument, which is `YES` if the host is available, otherwise `NO`.
@param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument which represents the various reachability states from the device to the `baseURL`.
@warning This method requires the `SystemConfiguration` framework. Add it in the active target's "Link Binary With Library" build phase, and add `#import <SystemConfiguration/SystemConfiguration.h>` to the header prefix of the project (Prefix.pch).
*/
#ifdef _SYSTEMCONFIGURATION_H
- (void)setReachabilityStatusChangeBlock:(void (^)(BOOL isNetworkReachable))block;
- (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block;
#endif
///-------------------------------

View File

@ -34,6 +34,11 @@
#ifdef _SYSTEMCONFIGURATION_H
#import <SystemConfiguration/SystemConfiguration.h>
#import <netinet/in.h>
#import <netinet6/in6.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
#endif
NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change";
@ -57,11 +62,11 @@ static NSString * const kAFMultipartFormBoundary = @"Boundary+0xAbCdEfGbOuNdArY"
#ifdef _SYSTEMCONFIGURATION_H
typedef SCNetworkReachabilityRef AFNetworkReachabilityRef;
typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status);
#else
typedef id AFNetworkReachabilityRef;
#endif
typedef void (^AFNetworkReachabilityStatusBlock)(BOOL isNetworkReachable);
typedef void (^AFCompletionBlock)(void);
static NSUInteger const kAFHTTPClientDefaultMaxConcurrentOperationCount = 4;
@ -230,8 +235,11 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
@property (readwrite, nonatomic, retain) NSMutableArray *registeredHTTPOperationClassNames;
@property (readwrite, nonatomic, retain) NSMutableDictionary *defaultHeaders;
@property (readwrite, nonatomic, retain) NSOperationQueue *operationQueue;
#ifdef _SYSTEMCONFIGURATION_H
@property (readwrite, nonatomic, assign) AFNetworkReachabilityRef networkReachability;
@property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
@property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock;
#endif
#ifdef _SYSTEMCONFIGURATION_H
- (void)startMonitoringNetworkReachability;
@ -246,8 +254,11 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
@synthesize registeredHTTPOperationClassNames = _registeredHTTPOperationClassNames;
@synthesize defaultHeaders = _defaultHeaders;
@synthesize operationQueue = _operationQueue;
#ifdef _SYSTEMCONFIGURATION_H
@synthesize networkReachability = _networkReachability;
@synthesize networkReachabilityStatus = _networkReachabilityStatus;
@synthesize networkReachabilityStatusBlock = _networkReachabilityStatusBlock;
#endif
+ (AFHTTPClient *)clientWithBaseURL:(NSURL *)url {
return [[[self alloc] initWithBaseURL:url] autorelease];
@ -283,6 +294,7 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
#endif
#ifdef _SYSTEMCONFIGURATION_H
self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown;
[self startMonitoringNetworkReachability];
#endif
@ -295,13 +307,13 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
- (void)dealloc {
#ifdef _SYSTEMCONFIGURATION_H
[self stopMonitoringNetworkReachability];
[_networkReachabilityStatusBlock release];
#endif
[_baseURL release];
[_registeredHTTPOperationClassNames release];
[_defaultHeaders release];
[_operationQueue release];
[_networkReachabilityStatusBlock release];
[super dealloc];
}
@ -313,25 +325,78 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
#pragma mark -
#ifdef _SYSTEMCONFIGURATION_H
static void AFReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
static BOOL AFURLHostIsIPAddress(NSURL *url) {
struct sockaddr_in sa_in;
struct sockaddr_in6 sa_in6;
return [url host] && (inet_pton(AF_INET, [[url host] UTF8String], &sa_in) == 1 || inet_pton(AF_INET6, [[url host] UTF8String], &sa_in6) == 1);
}
static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags) {
BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0);
BOOL isNetworkReachable = (isReachable && !needsConnection);
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown;
if(isNetworkReachable == NO){
status = AFNetworkReachabilityStatusNotReachable;
}
#if TARGET_OS_IPHONE
else if((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0){
status = AFNetworkReachabilityStatusReachableViaWWAN;
}
#endif
else {
status = AFNetworkReachabilityStatusReachableViaWiFi;
}
return status;
}
static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
AFNetworkReachabilityStatusBlock block = (AFNetworkReachabilityStatusBlock)info;
if (block) {
block(isNetworkReachable);
block(status);
}
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingReachabilityDidChangeNotification object:[NSNumber numberWithBool:isNetworkReachable]];
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingReachabilityDidChangeNotification object:[NSNumber numberWithInt:status]];
}
static const void * AFNetworkReachabilityRetainCallback(const void *info) {
return [(AFNetworkReachabilityStatusBlock)info copy];
}
static void AFNetworkReachabilityReleaseCallback(const void *info) {
[(AFNetworkReachabilityStatusBlock)info release];
}
- (void)startMonitoringNetworkReachability {
[self stopMonitoringNetworkReachability];
[self stopMonitoringNetworkReachability];
self.networkReachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [[self.baseURL host] UTF8String]);
SCNetworkReachabilityContext context = {0, self.networkReachabilityStatusBlock, NULL, NULL, NULL};
SCNetworkReachabilitySetCallback(self.networkReachability, AFReachabilityCallback, &context);
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status){
self.networkReachabilityStatus = status;
if (self.networkReachabilityStatusBlock) {
self.networkReachabilityStatusBlock(status);
}
};
SCNetworkReachabilityContext context = {0, callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context);
SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), (CFStringRef)NSRunLoopCommonModes);
/* Network reachability monitoring does not establish a baseline for IP addresses as it does for hostnames, so if the base URL host is an IP address, the initial reachability callback is manually triggered.
*/
if (AFURLHostIsIPAddress(self.baseURL)) {
SCNetworkReachabilityFlags flags;
SCNetworkReachabilityGetFlags(self.networkReachability, &flags);
dispatch_async(dispatch_get_main_queue(), ^{
AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
callback(status);
});
}
}
- (void)stopMonitoringNetworkReachability {
@ -341,9 +406,8 @@ static void AFReachabilityCallback(SCNetworkReachabilityRef __unused target, SCN
}
}
- (void)setReachabilityStatusChangeBlock:(void (^)(BOOL isNetworkReachable))block {
- (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block {
self.networkReachabilityStatusBlock = block;
[self startMonitoringNetworkReachability];
}
#endif
@ -474,9 +538,9 @@ static void AFReachabilityCallback(SCNetworkReachabilityRef __unused target, SCN
if (!operation) {
operation = [[[AFHTTPRequestOperation alloc] initWithRequest:urlRequest] autorelease];
}
[operation setCompletionBlockWithSuccess:success failure:failure];
return operation;
}

View File

@ -23,6 +23,13 @@
#import <Foundation/Foundation.h>
#import "AFURLConnectionOperation.h"
/**
Returns a set of MIME types detected in an HTTP `Accept` or `Content-Type` header.
*/
extern NSSet * AFContentTypesFromHTTPHeader(NSString *string);
extern NSString * AFCreateIncompleteDownloadDirectoryPath(void);
/**
`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.
*/
@ -37,30 +44,39 @@
*/
@property (readonly, nonatomic, retain) NSHTTPURLResponse *response;
/**
Set a target file for the response, will stream directly into this destination.
Defaults to nil, which will use a memory stream. Will create a new outputStream on change.
Note: Changing this while the request is not in ready state will be ignored.
*/
@property (nonatomic, copy) NSString *responseFilePath;
/**
Expected total length. This is different than expectedContentLength if the file is resumed.
On regular requests, this is equal to self.response.expectedContentLength unless we resume a request.
Note: this can also be -1 if the file size is not sent (*)
*/
@property (assign, readonly) long long totalContentLength;
/**
Indicator for the file offset on partial/resumed downloads.
This is greater than zero if the file download is resumed.
*/
@property (assign, readonly) long long offsetContentLength;
///----------------------------------------------------------
/// @name Managing And Checking For Acceptable HTTP Responses
///----------------------------------------------------------
/**
Returns an `NSIndexSet` object containing the ranges of acceptable HTTP status codes. When non-`nil`, the operation will set the `error` property to an error in `AFErrorDomain`. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
By default, this is the range 200 to 299, inclusive.
*/
@property (nonatomic, retain) NSIndexSet *acceptableStatusCodes;
/**
A Boolean value that corresponds to whether the status code of the response is within the specified set of acceptable status codes. Returns `YES` if `acceptableStatusCodes` is `nil`.
*/
@property (readonly) BOOL hasAcceptableStatusCode;
/**
Returns an `NSSet` object containing the acceptable MIME types. When non-`nil`, the operation will set the `error` property to an error in `AFErrorDomain`. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17
By default, this is `nil`.
*/
@property (nonatomic, retain) NSSet *acceptableContentTypes;
/**
A Boolean value that corresponds to whether the MIME type of the response is among the specified set of acceptable content types. Returns `YES` if `acceptableContentTypes` is `nil`.
*/
@ -76,6 +92,43 @@
*/
@property (nonatomic) dispatch_queue_t failureCallbackQueue;
///-------------------------------------------------------------
/// @name Managing Accceptable HTTP Status Codes & Content Types
///-------------------------------------------------------------
/**
Returns an `NSIndexSet` object containing the ranges of acceptable HTTP status codes. When non-`nil`, the operation will set the `error` property to an error in `AFErrorDomain`. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
By default, this is the range 200 to 299, inclusive.
*/
+ (NSIndexSet *)acceptableStatusCodes;
/**
Adds status codes to the set of acceptable HTTP status codes returned by `+acceptableStatusCodes` in subsequent calls by this class and its descendents.
@param statusCodes The status codes to be added to the set of acceptable HTTP status codes
*/
+ (void)addAcceptableStatusCodes:(NSIndexSet *)statusCodes;
/**
Returns an `NSSet` object containing the acceptable MIME types. When non-`nil`, the operation will set the `error` property to an error in `AFErrorDomain`. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17
By default, this is `nil`.
*/
+ (NSSet *)acceptableContentTypes;
/**
Adds content types to the set of acceptable MIME types returned by `+acceptableContentTypes` in subsequent calls by this class and its descendents.
@param contentTypes The content types to be added to the set of acceptable MIME types
*/
+ (void)addAcceptableContentTypes:(NSSet *)contentTypes;
///-----------------------------------------------------
/// @name Determining Whether A Request Can Be Processed
///-----------------------------------------------------
/**
A Boolean value determining whether or not the class can process the specified request. For example, `AFJSONRequestOperation` may check to make sure the content type was `application/json` or the URL path extension was `.json`.

View File

@ -21,6 +21,44 @@
// THE SOFTWARE.
#import "AFHTTPRequestOperation.h"
#import <objc/runtime.h>
NSString * const kAFNetworkingIncompleteDownloadDirectoryName = @"Incomplete";
NSSet * AFContentTypesFromHTTPHeader(NSString *string) {
static NSCharacterSet *_skippedCharacterSet = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_skippedCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@" ,"];
});
if (!string) {
return nil;
}
NSScanner *scanner = [NSScanner scannerWithString:string];
scanner.charactersToBeSkipped = _skippedCharacterSet;
NSMutableSet *mutableContentTypes = [NSMutableSet set];
while (![scanner isAtEnd]) {
NSString *contentType = nil;
if ([scanner scanUpToString:@";" intoString:&contentType]) {
[scanner scanUpToString:@"," intoString:nil];
}
if (contentType) {
[mutableContentTypes addObject:contentType];
}
}
return [NSSet setWithSet:mutableContentTypes];
}
static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL selector, void *block) {
Method originalMethod = class_getClassMethod(klass, selector);
IMP implementation = imp_implementationWithBlock(block);
class_replaceMethod(objc_getMetaClass([NSStringFromClass(klass) UTF8String]), selector, implementation, method_getTypeEncoding(originalMethod));
}
static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) {
NSMutableString *string = [NSMutableString string];
@ -52,33 +90,45 @@ static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) {
return string;
}
NSString * AFCreateIncompleteDownloadDirectoryPath(void) {
static NSString *incompleteDownloadPath;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *tempDirectory = NSTemporaryDirectory();
incompleteDownloadPath = [[tempDirectory stringByAppendingPathComponent:kAFNetworkingIncompleteDownloadDirectoryName] retain];
NSError *error = nil;
NSFileManager *fileMan = [[NSFileManager alloc] init];
if(![fileMan createDirectoryAtPath:incompleteDownloadPath withIntermediateDirectories:YES attributes:nil error:&error]) {
NSLog(@"Failed to create incomplete downloads directory at %@", incompleteDownloadPath);
}
[fileMan release];
});
return incompleteDownloadPath;
}
#pragma mark -
@interface AFHTTPRequestOperation ()
@property (readwrite, nonatomic, retain) NSURLRequest *request;
@property (readwrite, nonatomic, retain) NSHTTPURLResponse *response;
@property (readwrite, nonatomic, retain) NSError *HTTPError;
@property (assign) long long totalContentLength;
@property (assign) long long offsetContentLength;
@end
@implementation AFHTTPRequestOperation
@synthesize acceptableStatusCodes = _acceptableStatusCodes;
@synthesize acceptableContentTypes = _acceptableContentTypes;
@synthesize HTTPError = _HTTPError;
@synthesize responseFilePath = _responseFilePath;
@synthesize successCallbackQueue = _successCallbackQueue;
@synthesize failureCallbackQueue = _failureCallbackQueue;
- (id)initWithRequest:(NSURLRequest *)request {
self = [super initWithRequest:request];
if (!self) {
return nil;
}
self.acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)];
return self;
}
@synthesize totalContentLength = _totalContentLength;
@synthesize offsetContentLength = _offsetContentLength;
@dynamic request;
@dynamic response;
- (void)dealloc {
[_acceptableStatusCodes release];
[_acceptableContentTypes release];
[_HTTPError release];
if (_successCallbackQueue) {
@ -94,21 +144,17 @@ static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) {
[super dealloc];
}
- (NSHTTPURLResponse *)response {
return (NSHTTPURLResponse *)[super response];
}
- (NSError *)error {
if (self.response && !self.HTTPError) {
if (![self hasAcceptableStatusCode]) {
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
[userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected status code in (%@), got %d", nil), AFStringFromIndexSet(self.acceptableStatusCodes), [self.response statusCode]] forKey:NSLocalizedDescriptionKey];
[userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected status code in (%@), got %d", nil), AFStringFromIndexSet([[self class] acceptableStatusCodes]), [self.response statusCode]] forKey:NSLocalizedDescriptionKey];
[userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey];
self.HTTPError = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo] autorelease];
} else if ([self.responseData length] > 0 && ![self hasAcceptableContentType]) { // Don't invalidate content type if there is no content
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
[userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected content type %@, got %@", nil), self.acceptableContentTypes, [self.response MIMEType]] forKey:NSLocalizedDescriptionKey];
[userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected content type %@, got %@", nil), [[self class] acceptableContentTypes], [self.response MIMEType]] forKey:NSLocalizedDescriptionKey];
[userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey];
self.HTTPError = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo] autorelease];
@ -122,12 +168,30 @@ static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) {
}
}
- (void)pause {
unsigned long long offset = 0;
if ([self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey]) {
offset = [[self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey] unsignedLongLongValue];
} else {
offset = [[self.outputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey] length];
}
NSMutableURLRequest *mutableURLRequest = [[self.request mutableCopy] autorelease];
if ([[self.response allHeaderFields] valueForKey:@"ETag"]) {
[mutableURLRequest setValue:[[self.response allHeaderFields] valueForKey:@"ETag"] forHTTPHeaderField:@"If-Range"];
}
[mutableURLRequest setValue:[NSString stringWithFormat:@"bytes=%llu-", offset] forHTTPHeaderField:@"Range"];
self.request = mutableURLRequest;
[super pause];
}
- (BOOL)hasAcceptableStatusCode {
return !self.acceptableStatusCodes || [self.acceptableStatusCodes containsIndex:[self.response statusCode]];
return ![[self class] acceptableStatusCodes] || [[[self class] acceptableStatusCodes] containsIndex:[self.response statusCode]];
}
- (BOOL)hasAcceptableContentType {
return !self.acceptableContentTypes || [self.acceptableContentTypes containsObject:[self.response MIMEType]];
return ![[self class] acceptableContentTypes] || [[[self class] acceptableContentTypes] containsObject:[self.response MIMEType]];
}
- (void)setSuccessCallbackQueue:(dispatch_queue_t)successCallbackQueue {
@ -136,7 +200,7 @@ static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) {
dispatch_release(_successCallbackQueue);
_successCallbackQueue = NULL;
}
if (successCallbackQueue) {
dispatch_retain(successCallbackQueue);
_successCallbackQueue = successCallbackQueue;
@ -182,10 +246,85 @@ static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) {
};
}
#pragma mark - AFHTTPClientOperation
- (void)setResponseFilePath:(NSString *)responseFilePath {
if ([self isReady] && responseFilePath != _responseFilePath) {
[_responseFilePath release];
_responseFilePath = [responseFilePath retain];
if (responseFilePath) {
self.outputStream = [NSOutputStream outputStreamToFileAtPath:responseFilePath append:NO];
}else {
self.outputStream = [NSOutputStream outputStreamToMemory];
}
}
}
#pragma mark - AFHTTPRequestOperation
+ (NSIndexSet *)acceptableStatusCodes {
return [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)];
}
+ (void)addAcceptableStatusCodes:(NSIndexSet *)statusCodes {
NSMutableIndexSet *mutableStatusCodes = [[[NSMutableIndexSet alloc] initWithIndexSet:[self acceptableStatusCodes]] autorelease];
[mutableStatusCodes addIndexes:statusCodes];
AFSwizzleClassMethodWithClassAndSelectorUsingBlock([self class], @selector(acceptableStatusCodes), ^(id _self) {
return mutableStatusCodes;
});
}
+ (NSSet *)acceptableContentTypes {
return nil;
}
+ (void)addAcceptableContentTypes:(NSSet *)contentTypes {
NSMutableSet *mutableContentTypes = [[[NSMutableSet alloc] initWithSet:[self acceptableContentTypes] copyItems:YES] autorelease];
[mutableContentTypes unionSet:contentTypes];
AFSwizzleClassMethodWithClassAndSelectorUsingBlock([self class], @selector(acceptableContentTypes), ^(id _self) {
return mutableContentTypes;
});
}
+ (BOOL)canProcessRequest:(NSURLRequest *)request {
return YES;
if (![[self class] isEqual:[AFHTTPRequestOperation class]]) {
return YES;
}
return [[self acceptableContentTypes] intersectsSet:AFContentTypesFromHTTPHeader([request valueForHTTPHeaderField:@"Accept"])];
}
#pragma mark - NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection
didReceiveResponse:(NSURLResponse *)response
{
self.response = (NSHTTPURLResponse *)response;
// 206 = Partial Content.
long long totalContentLength = self.response.expectedContentLength;
long long fileOffset = 0;
if ([self.response statusCode] != 206) {
if ([self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey]) {
[self.outputStream setProperty:[NSNumber numberWithInteger:0] forKey:NSStreamFileCurrentOffsetKey];
} else {
if ([[self.outputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey] length] > 0) {
self.outputStream = [NSOutputStream outputStreamToMemory];
}
}
}else {
NSString *contentRange = [self.response.allHeaderFields valueForKey:@"Content-Range"];
if ([contentRange hasPrefix:@"bytes"]) {
NSArray *bytes = [contentRange componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" -/"]];
if ([bytes count] == 4) {
fileOffset = [[bytes objectAtIndex:1] longLongValue];
totalContentLength = [[bytes objectAtIndex:2] longLongValue] ?: -1; // if this is *, it's converted to 0, but -1 is default.
}
}
}
self.offsetContentLength = MAX(fileOffset, 0);
self.totalContentLength = totalContentLength;
[self.outputStream open];
}
@end

View File

@ -37,9 +37,6 @@ static dispatch_queue_t image_request_operation_processing_queue() {
#elif __MAC_OS_X_VERSION_MIN_REQUIRED
@property (readwrite, nonatomic, retain) NSImage *responseImage;
#endif
+ (NSSet *)defaultAcceptableContentTypes;
+ (NSSet *)defaultAcceptablePathExtensions;
@end
@implementation AFImageRequestOperation
@ -136,22 +133,12 @@ static dispatch_queue_t image_request_operation_processing_queue() {
}
#endif
+ (NSSet *)defaultAcceptableContentTypes {
return [NSSet setWithObjects:@"image/tiff", @"image/jpeg", @"image/gif", @"image/png", @"image/ico", @"image/x-icon", @"image/bmp", @"image/x-bmp", @"image/x-xbitmap", @"image/x-win-bitmap", nil];
}
+ (NSSet *)defaultAcceptablePathExtensions {
return [NSSet setWithObjects:@"tif", @"tiff", @"jpg", @"jpeg", @"gif", @"png", @"ico", @"bmp", @"cur", nil];
}
- (id)initWithRequest:(NSURLRequest *)urlRequest {
self = [super initWithRequest:urlRequest];
if (!self) {
return nil;
}
self.acceptableContentTypes = [[self class] defaultAcceptableContentTypes];
#if __IPHONE_OS_VERSION_MIN_REQUIRED
self.imageScale = [[UIScreen mainScreen] scale];
#endif
@ -200,33 +187,19 @@ static dispatch_queue_t image_request_operation_processing_queue() {
#pragma mark - AFHTTPClientOperation
+ (BOOL)canProcessRequest:(NSURLRequest *)request {
return [[self defaultAcceptableContentTypes] containsObject:[request valueForHTTPHeaderField:@"Accept"]] || [[self defaultAcceptablePathExtensions] containsObject:[[request URL] pathExtension]];
+ (NSSet *)acceptableContentTypes {
return [NSSet setWithObjects:@"image/tiff", @"image/jpeg", @"image/gif", @"image/png", @"image/ico", @"image/x-icon", @"image/bmp", @"image/x-bmp", @"image/x-xbitmap", @"image/x-win-bitmap", nil];
}
#if __IPHONE_OS_VERSION_MIN_REQUIRED
+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure
{
return [self imageRequestOperationWithRequest:urlRequest imageProcessingBlock:nil cacheName:nil success:^(NSURLRequest __unused *request, NSHTTPURLResponse __unused *response, UIImage *image) {
success(image);
} failure:^(NSURLRequest __unused *request, NSHTTPURLResponse *response, NSError *error) {
failure(response, error);
}];
+ (BOOL)canProcessRequest:(NSURLRequest *)request {
static NSSet * _acceptablePathExtension = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_acceptablePathExtension = [[NSSet alloc] initWithObjects:@"tif", @"tiff", @"jpg", @"jpeg", @"gif", @"png", @"ico", @"bmp", @"cur", nil];
});
return [_acceptablePathExtension containsObject:[[request URL] pathExtension]] || [super canProcessRequest:request];
}
#elif __MAC_OS_X_VERSION_MIN_REQUIRED
+ (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)urlRequest
success:(void (^)(id object))success
failure:(void (^)(NSHTTPURLResponse *response, NSError *error))failure
{
return [self imageRequestOperationWithRequest:urlRequest imageProcessingBlock:nil cacheName:nil success:^(NSURLRequest __unused *request, NSHTTPURLResponse __unused *response, NSImage *image) {
success(image);
} failure:^(NSURLRequest __unused *request, NSHTTPURLResponse *response, NSError *error) {
failure(response, error);
}];
}
#endif
- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure

View File

@ -35,9 +35,6 @@ static dispatch_queue_t json_request_operation_processing_queue() {
@interface AFJSONRequestOperation ()
@property (readwrite, nonatomic, retain) id responseJSON;
@property (readwrite, nonatomic, retain) NSError *JSONError;
+ (NSSet *)defaultAcceptableContentTypes;
+ (NSSet *)defaultAcceptablePathExtensions;
@end
@implementation AFJSONRequestOperation
@ -62,29 +59,6 @@ static dispatch_queue_t json_request_operation_processing_queue() {
return requestOperation;
}
+ (NSSet *)defaultAcceptableContentTypes {
return [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];
}
+ (NSSet *)defaultAcceptablePathExtensions {
return [NSSet setWithObjects:@"json", nil];
}
+ (BOOL)canProcessRequest:(NSURLRequest *)request {
return [[self defaultAcceptableContentTypes] containsObject:[request valueForHTTPHeaderField:@"Accept"]] || [[self defaultAcceptablePathExtensions] containsObject:[[request URL] pathExtension]];
}
- (id)initWithRequest:(NSURLRequest *)urlRequest {
self = [super initWithRequest:urlRequest];
if (!self) {
return nil;
}
self.acceptableContentTypes = [[self class] defaultAcceptableContentTypes];
return self;
}
- (void)dealloc {
[_responseJSON release];
[_JSONError release];
@ -115,6 +89,16 @@ static dispatch_queue_t json_request_operation_processing_queue() {
}
}
#pragma mark - AFHTTPRequestOperation
+ (NSSet *)acceptableContentTypes {
return [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];
}
+ (BOOL)canProcessRequest:(NSURLRequest *)request {
return [[[request URL] pathExtension] isEqualToString:@"json"] || [super canProcessRequest:request];
}
- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{

View File

@ -35,9 +35,6 @@ static dispatch_queue_t property_list_request_operation_processing_queue() {
@property (readwrite, nonatomic, retain) id responsePropertyList;
@property (readwrite, nonatomic, assign) NSPropertyListFormat propertyListFormat;
@property (readwrite, nonatomic, retain) NSError *propertyListError;
+ (NSSet *)defaultAcceptableContentTypes;
+ (NSSet *)defaultAcceptablePathExtensions;
@end
@implementation AFPropertyListRequestOperation
@ -64,22 +61,12 @@ static dispatch_queue_t property_list_request_operation_processing_queue() {
return requestOperation;
}
+ (NSSet *)defaultAcceptableContentTypes {
return [NSSet setWithObjects:@"application/x-plist", nil];
}
+ (NSSet *)defaultAcceptablePathExtensions {
return [NSSet setWithObjects:@"plist", nil];
}
- (id)initWithRequest:(NSURLRequest *)urlRequest {
self = [super initWithRequest:urlRequest];
if (!self) {
return nil;
}
self.acceptableContentTypes = [[self class] defaultAcceptableContentTypes];
self.propertyListReadOptions = NSPropertyListImmutable;
return self;
@ -111,8 +98,14 @@ static dispatch_queue_t property_list_request_operation_processing_queue() {
}
}
#pragma mark - AFHTTPRequestOperation
+ (NSSet *)acceptableContentTypes {
return [NSSet setWithObjects:@"application/x-plist", nil];
}
+ (BOOL)canProcessRequest:(NSURLRequest *)request {
return [[self defaultAcceptableContentTypes] containsObject:[request valueForHTTPHeaderField:@"Accept"]] || [[self defaultAcceptablePathExtensions] containsObject:[[request URL] pathExtension]];
return [[[request URL] pathExtension] isEqualToString:@"plist"] || [super canProcessRequest:request];
}
- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success

View File

@ -135,7 +135,7 @@ extern NSString * const AFNetworkingOperationDidFinishNotification;
/**
The output stream that is used to write data received until the request is finished.
@discussion 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`.
@discussion 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.
*/
@property (nonatomic, retain) NSOutputStream *outputStream;
@ -152,6 +152,44 @@ extern NSString * const AFNetworkingOperationDidFinishNotification;
*/
- (id)initWithRequest:(NSURLRequest *)urlRequest;
///----------------------------------
/// @name Pausing / Resuming Requests
///----------------------------------
/**
Pauses the execution of the request operation.
@discussion A paused operation returns `NO` for `-isReady`, `-isExecuting`, and `-isFinished`. As such, it will remain in an `NSOperationQueue` until it is either cancelled or resumed. Pausing a finished or cancelled operation has no effect.
*/
- (void)pause;
/**
Whether the request operation is currently paused.
@return `YES` if the operation is currently paused, otherwise `NO`.
*/
- (BOOL)isPaused;
/**
Resumes the execution of the paused request operation.
@discussion Pause/Resume behavior varies depending on the underlying implementation for the operation class. In its base implementation, resuming a paused requests restarts the original request. However, since HTTP defines a specification for how to request a specific content range, `AFHTTPRequestOperation` will resume downloading the request from where it left off, instead of restarting the original request.
*/
- (void)resume;
///----------------------------------------------
/// @name Configuring Backgrounding Task Behavior
///----------------------------------------------
/**
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 __IPHONE_OS_VERSION_MIN_REQUIRED
- (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))handler;
#endif
///---------------------------------
/// @name Setting Progress Callbacks
///---------------------------------
@ -163,7 +201,7 @@ extern NSString * const AFNetworkingOperationDidFinishNotification;
@see setDownloadProgressBlock
*/
- (void)setUploadProgressBlock:(void (^)(NSInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite))block;
- (void)setUploadProgressBlock:(void (^)(NSInteger 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.
@ -172,7 +210,7 @@ extern NSString * const AFNetworkingOperationDidFinishNotification;
@see setUploadProgressBlock
*/
- (void)setDownloadProgressBlock:(void (^)(NSInteger bytesRead, NSInteger totalBytesRead, NSInteger totalBytesExpectedToRead))block;
- (void)setDownloadProgressBlock:(void (^)(NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))block;
///-------------------------------------------------
/// @name Setting NSURLConnection Delegate Callbacks

View File

@ -23,12 +23,19 @@
#import "AFURLConnectionOperation.h"
typedef enum {
AFHTTPOperationPausedState = -1,
AFHTTPOperationReadyState = 1,
AFHTTPOperationExecutingState = 2,
AFHTTPOperationFinishedState = 3,
} _AFOperationState;
typedef unsigned short AFOperationState;
typedef signed short AFOperationState;
#if __IPHONE_OS_VERSION_MIN_REQUIRED
typedef UIBackgroundTaskIdentifier AFBackgroundTaskIdentifier;
#else
typedef id AFBackgroundTaskIdentifier;
#endif
static NSUInteger const kAFHTTPMinimumInitialDataCapacity = 1024;
static NSUInteger const kAFHTTPMaximumInitialDataCapacity = 1024 * 1024 * 8;
@ -40,7 +47,7 @@ NSString * const AFNetworkingErrorDomain = @"com.alamofire.networking.error";
NSString * const AFNetworkingOperationDidStartNotification = @"com.alamofire.networking.operation.start";
NSString * const AFNetworkingOperationDidFinishNotification = @"com.alamofire.networking.operation.finish";
typedef void (^AFURLConnectionOperationProgressBlock)(NSInteger bytes, NSInteger totalBytes, NSInteger totalBytesExpected);
typedef void (^AFURLConnectionOperationProgressBlock)(NSInteger bytes, long long totalBytes, long long totalBytesExpected);
typedef BOOL (^AFURLConnectionOperationAuthenticationAgainstProtectionSpaceBlock)(NSURLConnection *connection, NSURLProtectionSpace *protectionSpace);
typedef void (^AFURLConnectionOperationAuthenticationChallengeBlock)(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge);
typedef NSCachedURLResponse * (^AFURLConnectionOperationCacheResponseBlock)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse);
@ -53,6 +60,8 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
return @"isExecuting";
case AFHTTPOperationFinishedState:
return @"isFinished";
case AFHTTPOperationPausedState:
return @"isPaused";
default:
return @"state";
}
@ -62,6 +71,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
switch (fromState) {
case AFHTTPOperationReadyState:
switch (toState) {
case AFHTTPOperationPausedState:
case AFHTTPOperationExecutingState:
return YES;
case AFHTTPOperationFinishedState:
@ -71,6 +81,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
}
case AFHTTPOperationExecutingState:
switch (toState) {
case AFHTTPOperationPausedState:
case AFHTTPOperationFinishedState:
return YES;
default:
@ -78,6 +89,8 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
}
case AFHTTPOperationFinishedState:
return NO;
case AFHTTPOperationPausedState:
return toState == AFHTTPOperationReadyState;
default:
return YES;
}
@ -93,8 +106,8 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
@property (readwrite, nonatomic, retain) NSError *error;
@property (readwrite, nonatomic, retain) NSData *responseData;
@property (readwrite, nonatomic, copy) NSString *responseString;
@property (readwrite, nonatomic, assign) NSInteger totalBytesRead;
@property (readwrite, nonatomic, retain) NSMutableData *dataAccumulator;
@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;
@property (readwrite, nonatomic, copy) AFURLConnectionOperationAuthenticationAgainstProtectionSpaceBlock authenticationAgainstProtectionSpace;
@ -116,9 +129,9 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
@synthesize responseData = _responseData;
@synthesize responseString = _responseString;
@synthesize totalBytesRead = _totalBytesRead;
@synthesize dataAccumulator = _dataAccumulator;
@dynamic inputStream;
@synthesize outputStream = _outputStream;
@synthesize backgroundTaskIdentifier = _backgroundTaskIdentifier;
@synthesize uploadProgress = _uploadProgress;
@synthesize downloadProgress = _downloadProgress;
@synthesize authenticationAgainstProtectionSpace = _authenticationAgainstProtectionSpace;
@ -158,7 +171,9 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
self.runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes];
self.request = urlRequest;
self.outputStream = [NSOutputStream outputStreamToMemory];
self.state = AFHTTPOperationReadyState;
return self;
@ -175,13 +190,19 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
[_responseData release];
[_responseString release];
[_dataAccumulator release];
if (_outputStream) {
[_outputStream close];
[_outputStream release];
_outputStream = nil;
}
#if __IPHONE_OS_VERSION_MIN_REQUIRED
if (_backgroundTaskIdentifier) {
[[UIApplication sharedApplication] endBackgroundTask:_backgroundTaskIdentifier];
_backgroundTaskIdentifier = UIBackgroundTaskInvalid;
}
#endif
[_uploadProgress release];
[_downloadProgress release];
@ -217,16 +238,51 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
}
- (void)setInputStream:(NSInputStream *)inputStream {
[self willChangeValueForKey:@"inputStream"];
NSMutableURLRequest *mutableRequest = [[self.request mutableCopy] autorelease];
mutableRequest.HTTPBodyStream = inputStream;
self.request = mutableRequest;
[self didChangeValueForKey:@"inputStream"];
}
- (void)setUploadProgressBlock:(void (^)(NSInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite))block {
- (void)setOutputStream:(NSOutputStream *)outputStream {
[self willChangeValueForKey:@"outputStream"];
[outputStream retain];
[_outputStream release];
_outputStream = outputStream;
[self didChangeValueForKey:@"outputStream"];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
for (NSString *runLoopMode in self.runLoopModes) {
[self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode];
}
}
#if __IPHONE_OS_VERSION_MIN_REQUIRED
- (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))handler {
[self.lock lock];
if (!self.backgroundTaskIdentifier) {
UIApplication *application = [UIApplication sharedApplication];
self.backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^{
if (handler) {
handler();
}
[self cancel];
[application endBackgroundTask:self.backgroundTaskIdentifier];
self.backgroundTaskIdentifier = UIBackgroundTaskInvalid;
}];
}
[self.lock unlock];
}
#endif
- (void)setUploadProgressBlock:(void (^)(NSInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))block {
self.uploadProgress = block;
}
- (void)setDownloadProgressBlock:(void (^)(NSInteger bytesRead, NSInteger totalBytesRead, NSInteger totalBytesExpectedToRead))block {
- (void)setDownloadProgressBlock:(void (^)(NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))block {
self.downloadProgress = block;
}
@ -283,6 +339,35 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
return _responseString;
}
- (void)pause {
if ([self isPaused]) {
return;
}
[self.lock lock];
self.state = AFHTTPOperationPausedState;
[self.connection performSelector:@selector(cancel) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
[self.lock unlock];
}
- (BOOL)isPaused {
return self.state == AFHTTPOperationPausedState;
}
- (void)resume {
if (![self isPaused]) {
return;
}
[self.lock lock];
self.state = AFHTTPOperationReadyState;
[self start];
[self.lock unlock];
}
#pragma mark - NSOperation
- (BOOL)isReady {
@ -431,43 +516,30 @@ totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
- (void)connection:(NSURLConnection *)__unused connection
didReceiveResponse:(NSURLResponse *)response
{
self.response = (NSHTTPURLResponse *)response;
self.response = response;
if (self.outputStream) {
[self.outputStream open];
} else {
NSUInteger maxCapacity = MAX((NSUInteger)llabs(response.expectedContentLength), kAFHTTPMinimumInitialDataCapacity);
NSUInteger capacity = MIN(maxCapacity, kAFHTTPMaximumInitialDataCapacity);
self.dataAccumulator = [NSMutableData dataWithCapacity:capacity];
}
[self.outputStream open];
}
- (void)connection:(NSURLConnection *)__unused connection
didReceiveData:(NSData *)data
didReceiveData:(NSData *)data
{
self.totalBytesRead += [data length];
if (self.outputStream) {
if ([self.outputStream hasSpaceAvailable]) {
const uint8_t *dataBuffer = (uint8_t *) [data bytes];
[self.outputStream write:&dataBuffer[0] maxLength:[data length]];
}
} else {
[self.dataAccumulator appendData:data];
if ([self.outputStream hasSpaceAvailable]) {
const uint8_t *dataBuffer = (uint8_t *) [data bytes];
[self.outputStream write:&dataBuffer[0] maxLength:[data length]];
}
if (self.downloadProgress) {
self.downloadProgress([data length], self.totalBytesRead, (NSInteger)self.response.expectedContentLength);
self.downloadProgress((long long)[data length], self.totalBytesRead, self.response.expectedContentLength);
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)__unused connection {
if (self.outputStream) {
[self.outputStream close];
} else {
self.responseData = [NSData dataWithData:self.dataAccumulator];
[_dataAccumulator release]; _dataAccumulator = nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)__unused connection {
self.responseData = [self.outputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
[self.outputStream close];
[self finish];
@ -479,11 +551,7 @@ didReceiveResponse:(NSURLResponse *)response
{
self.error = error;
if (self.outputStream) {
[self.outputStream close];
} else {
[_dataAccumulator release]; _dataAccumulator = nil;
}
[self.outputStream close];
[self finish];

View File

@ -39,9 +39,6 @@ static dispatch_queue_t xml_request_operation_processing_queue() {
@property (readwrite, nonatomic, retain) NSXMLDocument *responseXMLDocument;
#endif
@property (readwrite, nonatomic, retain) NSError *XMLError;
+ (NSSet *)defaultAcceptableContentTypes;
+ (NSSet *)defaultAcceptablePathExtensions;
@end
@implementation AFXMLRequestOperation
@ -91,25 +88,6 @@ static dispatch_queue_t xml_request_operation_processing_queue() {
}
#endif
+ (NSSet *)defaultAcceptableContentTypes {
return [NSSet setWithObjects:@"application/xml", @"text/xml", nil];
}
+ (NSSet *)defaultAcceptablePathExtensions {
return [NSSet setWithObjects:@"xml", nil];
}
- (id)initWithRequest:(NSURLRequest *)urlRequest {
self = [super initWithRequest:urlRequest];
if (!self) {
return nil;
}
self.acceptableContentTypes = [[self class] defaultAcceptableContentTypes];
return self;
}
- (void)dealloc {
[_responseXMLParser release];
@ -158,8 +136,14 @@ static dispatch_queue_t xml_request_operation_processing_queue() {
self.responseXMLParser.delegate = nil;
}
#pragma mark - AFHTTPRequestOperation
+ (NSSet *)acceptableContentTypes {
return [NSSet setWithObjects:@"application/xml", @"text/xml", nil];
}
+ (BOOL)canProcessRequest:(NSURLRequest *)request {
return [[self defaultAcceptableContentTypes] containsObject:[request valueForHTTPHeaderField:@"Accept"]] || [[self defaultAcceptablePathExtensions] containsObject:[[request URL] pathExtension]];
return [[[request URL] pathExtension] isEqualToString:@"xml"] || [super canProcessRequest:request];
}
- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success

View File

@ -25,6 +25,7 @@
F8A27AC9142CFE1300F5E0D6 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = F8A27AB9142CFE1300F5E0D6 /* Credits.rtf */; };
F8A27ACA142CFE1300F5E0D6 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = F8A27ABB142CFE1300F5E0D6 /* MainMenu.xib */; };
F8A27ACB142CFE1300F5E0D6 /* JSONKit.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A27AC0142CFE1300F5E0D6 /* JSONKit.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc -w -Xanalyzer -analyzer-disable-checker"; }; };
F8BF7FE4153234BB00885289 /* AFDownloadRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F8BF7FE3153234BB00885289 /* AFDownloadRequestOperation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
F8CEEB6F142CEC6E00247B03 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8CEEB6E142CEC6E00247B03 /* Cocoa.framework */; };
/* End PBXBuildFile section */
@ -63,6 +64,8 @@
F8A27AC0142CFE1300F5E0D6 /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = "<group>"; };
F8A27AC4142CFE1300F5E0D6 /* Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Prefix.pch; sourceTree = "<group>"; };
F8A27AC5142CFE1300F5E0D6 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
F8BF7FE2153234BB00885289 /* AFDownloadRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFDownloadRequestOperation.h; sourceTree = "<group>"; };
F8BF7FE3153234BB00885289 /* AFDownloadRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFDownloadRequestOperation.m; sourceTree = "<group>"; };
F8CEEB6A142CEC6E00247B03 /* AFNetworking Mac Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "AFNetworking Mac Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
F8CEEB6E142CEC6E00247B03 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
F8CEEB71142CEC6E00247B03 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
@ -128,6 +131,8 @@
F87A159E1444926300318955 /* AFURLConnectionOperation.m */,
F897DE6B142CFEDC000DDD35 /* AFHTTPRequestOperation.h */,
F897DE6C142CFEDC000DDD35 /* AFHTTPRequestOperation.m */,
F8BF7FE2153234BB00885289 /* AFDownloadRequestOperation.h */,
F8BF7FE3153234BB00885289 /* AFDownloadRequestOperation.m */,
F897DE71142CFEDC000DDD35 /* AFJSONRequestOperation.h */,
F897DE72142CFEDC000DDD35 /* AFJSONRequestOperation.m */,
F87A15A01444926900318955 /* AFXMLRequestOperation.h */,
@ -287,6 +292,7 @@
F87A159F1444926300318955 /* AFURLConnectionOperation.m in Sources */,
F897DE78142CFEDC000DDD35 /* AFHTTPClient.m in Sources */,
F897DE79142CFEDC000DDD35 /* AFHTTPRequestOperation.m in Sources */,
F8BF7FE4153234BB00885289 /* AFDownloadRequestOperation.m in Sources */,
F897DE7B142CFEDC000DDD35 /* AFImageRequestOperation.m in Sources */,
F897DE7C142CFEDC000DDD35 /* AFJSONRequestOperation.m in Sources */,
F87A15A21444926A00318955 /* AFXMLRequestOperation.m in Sources */,