merged multipart streaming thingy
This commit is contained in:
commit
5a790360df
16 changed files with 249 additions and 137 deletions
|
|
@ -124,8 +124,14 @@ extern NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *paramete
|
||||||
[NSURL URLWithString:@"/foo/" relativeToURL:baseURL]; // http://example.com/foo/
|
[NSURL URLWithString:@"/foo/" relativeToURL:baseURL]; // http://example.com/foo/
|
||||||
[NSURL URLWithString:@"http://example2.com/" relativeToURL:baseURL]; // http://example2.com/
|
[NSURL URLWithString:@"http://example2.com/" relativeToURL:baseURL]; // http://example2.com/
|
||||||
|
|
||||||
|
## NSCoding / NSCopying Conformance
|
||||||
|
|
||||||
|
`AFHTTPClient` 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:
|
||||||
|
|
||||||
|
- 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.
|
||||||
*/
|
*/
|
||||||
@interface AFHTTPClient : NSObject
|
@interface AFHTTPClient : NSObject <NSCoding, NSCopying>
|
||||||
|
|
||||||
///---------------------------------------
|
///---------------------------------------
|
||||||
/// @name Accessing HTTP Client Properties
|
/// @name Accessing HTTP Client Properties
|
||||||
|
|
@ -210,7 +216,7 @@ extern NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *paramete
|
||||||
|
|
||||||
@param The subclass of `AFHTTPRequestOperation` to register
|
@param The subclass of `AFHTTPRequestOperation` to register
|
||||||
|
|
||||||
@return `YES` if the registration is successful, `NO` otherwise. The only failure condition is if `operationClass` does is not a subclass of `AFHTTPRequestOperation`.
|
@return `YES` if the registration is successful, `NO` otherwise. The only failure condition is if `operationClass` is not a subclass of `AFHTTPRequestOperation`.
|
||||||
|
|
||||||
@discussion When `enqueueHTTPRequestOperationWithRequest:success:failure` is invoked, each registered class is consulted in turn to see if it can handle the specific request. The first class to return `YES` when sent a `canProcessRequest:` message is used to create an operation using `initWithURLRequest:` and do `setCompletionBlockWithSuccess:failure:`. There is no guarantee that all registered classes will be consulted. Classes are consulted in the reverse order of their registration. Attempting to register an already-registered class will move it to the top of the list.
|
@discussion When `enqueueHTTPRequestOperationWithRequest:success:failure` is invoked, each registered class is consulted in turn to see if it can handle the specific request. The first class to return `YES` when sent a `canProcessRequest:` message is used to create an operation using `initWithURLRequest:` and do `setCompletionBlockWithSuccess:failure:`. There is no guarantee that all registered classes will be consulted. Classes are consulted in the reverse order of their registration. Attempting to register an already-registered class will move it to the top of the list.
|
||||||
|
|
||||||
|
|
@ -423,7 +429,7 @@ extern NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *paramete
|
||||||
Creates an `AFHTTPRequestOperation` with a `DELETE` request, and enqueues it to the HTTP client's operation queue.
|
Creates an `AFHTTPRequestOperation` with a `DELETE` request, and enqueues it to the HTTP client's operation queue.
|
||||||
|
|
||||||
@param path The path to be appended to the HTTP client's base URL and used as the request URL.
|
@param path The path to be appended to the HTTP client's base URL and used as the request URL.
|
||||||
@param parameters The parameters to be encoded and set in the request HTTP body.
|
@param parameters The parameters to be encoded and appended as the query string for the request URL.
|
||||||
@param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes two arguments: the created request operation and the object created from the response data of request.
|
@param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes two arguments: the created request operation and the object created from the response data of request.
|
||||||
@param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data. This block has no return value and takes two arguments:, the created request operation and the `NSError` object describing the network or parsing error that occurred.
|
@param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the resonse data. This block has no return value and takes two arguments:, the created request operation and the `NSError` object describing the network or parsing error that occurred.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,8 +77,6 @@ typedef id AFNetworkReachabilityRef;
|
||||||
|
|
||||||
typedef void (^AFCompletionBlock)(void);
|
typedef void (^AFCompletionBlock)(void);
|
||||||
|
|
||||||
static NSUInteger const kAFHTTPClientDefaultMaxConcurrentOperationCount = 4;
|
|
||||||
|
|
||||||
static NSString * AFBase64EncodedStringFromString(NSString *string) {
|
static NSString * AFBase64EncodedStringFromString(NSString *string) {
|
||||||
NSData *data = [NSData dataWithBytes:[string UTF8String] length:[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
|
NSData *data = [NSData dataWithBytes:[string UTF8String] length:[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
|
||||||
NSUInteger length = [data length];
|
NSUInteger length = [data length];
|
||||||
|
|
@ -270,6 +268,11 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected
|
||||||
|
if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
|
||||||
|
url = [url URLByAppendingPathComponent:@""];
|
||||||
|
}
|
||||||
|
|
||||||
self.baseURL = url;
|
self.baseURL = url;
|
||||||
|
|
||||||
self.stringEncoding = NSUTF8StringEncoding;
|
self.stringEncoding = NSUTF8StringEncoding;
|
||||||
|
|
@ -299,7 +302,7 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
self.operationQueue = [[[NSOperationQueue alloc] init] autorelease];
|
self.operationQueue = [[[NSOperationQueue alloc] init] autorelease];
|
||||||
[self.operationQueue setMaxConcurrentOperationCount:kAFHTTPClientDefaultMaxConcurrentOperationCount];
|
[self.operationQueue setMaxConcurrentOperationCount:NSOperationQueueDefaultMaxConcurrentOperationCount];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
@ -672,6 +675,47 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) {
|
||||||
[self enqueueHTTPRequestOperation:operation];
|
[self enqueueHTTPRequestOperation:operation];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - NSCoding
|
||||||
|
|
||||||
|
- (id)initWithCoder:(NSCoder *)aDecoder {
|
||||||
|
NSURL *baseURL = [aDecoder decodeObjectForKey:@"baseURL"];
|
||||||
|
|
||||||
|
self = [self initWithBaseURL:baseURL];
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.stringEncoding = [aDecoder decodeIntegerForKey:@"stringEncoding"];
|
||||||
|
self.parameterEncoding = [aDecoder decodeIntegerForKey:@"parameterEncoding"];
|
||||||
|
self.registeredHTTPOperationClassNames = [aDecoder decodeObjectForKey:@"registeredHTTPOperationClassNames"];
|
||||||
|
self.defaultHeaders = [aDecoder decodeObjectForKey:@"defaultHeaders"];
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||||
|
[aCoder encodeObject:self.baseURL forKey:@"baseURL"];
|
||||||
|
[aCoder encodeInteger:self.stringEncoding forKey:@"stringEncoding"];
|
||||||
|
[aCoder encodeInteger:self.parameterEncoding forKey:@"parameterEncoding"];
|
||||||
|
[aCoder encodeObject:self.registeredHTTPOperationClassNames forKey:@"registeredHTTPOperationClassNames"];
|
||||||
|
[aCoder encodeObject:self.defaultHeaders forKey:@"defaultHeaders"];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - NSCopying
|
||||||
|
|
||||||
|
- (id)copyWithZone:(NSZone *)zone {
|
||||||
|
AFHTTPClient *HTTPClient = [[[self class] allocWithZone:zone] initWithBaseURL:self.baseURL];
|
||||||
|
|
||||||
|
HTTPClient.stringEncoding = self.stringEncoding;
|
||||||
|
HTTPClient.parameterEncoding = self.parameterEncoding;
|
||||||
|
HTTPClient.registeredHTTPOperationClassNames = [[self.registeredHTTPOperationClassNames copyWithZone:zone] autorelease];
|
||||||
|
HTTPClient.defaultHeaders = [[self.defaultHeaders copyWithZone:zone] autorelease];
|
||||||
|
#ifdef _SYSTEMCONFIGURATION_H
|
||||||
|
HTTPClient.networkReachabilityStatusBlock = self.networkReachabilityStatusBlock;
|
||||||
|
#endif
|
||||||
|
return HTTPClient;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,6 @@
|
||||||
*/
|
*/
|
||||||
extern NSSet * AFContentTypesFromHTTPHeader(NSString *string);
|
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.
|
`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.
|
||||||
*/
|
*/
|
||||||
|
|
@ -44,30 +42,6 @@ extern NSString * AFCreateIncompleteDownloadDirectoryPath(void);
|
||||||
*/
|
*/
|
||||||
@property (readonly, nonatomic, retain) NSHTTPURLResponse *response;
|
@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
|
/// @name Managing And Checking For Acceptable HTTP Responses
|
||||||
///----------------------------------------------------------
|
///----------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,6 @@
|
||||||
#import "AFHTTPRequestOperation.h"
|
#import "AFHTTPRequestOperation.h"
|
||||||
#import <objc/runtime.h>
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
NSString * const kAFNetworkingIncompleteDownloadDirectoryName = @"Incomplete";
|
|
||||||
|
|
||||||
NSSet * AFContentTypesFromHTTPHeader(NSString *string) {
|
NSSet * AFContentTypesFromHTTPHeader(NSString *string) {
|
||||||
static NSCharacterSet *_skippedCharacterSet = nil;
|
static NSCharacterSet *_skippedCharacterSet = nil;
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
|
|
@ -77,11 +75,11 @@ static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (range.length == 1) {
|
if (range.length == 1) {
|
||||||
[string appendFormat:@"%u", range.location];
|
[string appendFormat:@"%lu", (long)range.location];
|
||||||
} else {
|
} else {
|
||||||
NSUInteger firstIndex = range.location;
|
NSUInteger firstIndex = range.location;
|
||||||
NSUInteger lastIndex = firstIndex + range.length - 1;
|
NSUInteger lastIndex = firstIndex + range.length - 1;
|
||||||
[string appendFormat:@"%u-%u", firstIndex, lastIndex];
|
[string appendFormat:@"%lu-%lu", (long)firstIndex, (long)lastIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
range.location = nextIndex;
|
range.location = nextIndex;
|
||||||
|
|
@ -91,24 +89,6 @@ static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) {
|
||||||
return string;
|
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 -
|
#pragma mark -
|
||||||
|
|
||||||
@interface AFHTTPRequestOperation ()
|
@interface AFHTTPRequestOperation ()
|
||||||
|
|
@ -121,7 +101,6 @@ NSString * AFCreateIncompleteDownloadDirectoryPath(void) {
|
||||||
|
|
||||||
@implementation AFHTTPRequestOperation
|
@implementation AFHTTPRequestOperation
|
||||||
@synthesize HTTPError = _HTTPError;
|
@synthesize HTTPError = _HTTPError;
|
||||||
@synthesize responseFilePath = _responseFilePath;
|
|
||||||
@synthesize successCallbackQueue = _successCallbackQueue;
|
@synthesize successCallbackQueue = _successCallbackQueue;
|
||||||
@synthesize failureCallbackQueue = _failureCallbackQueue;
|
@synthesize failureCallbackQueue = _failureCallbackQueue;
|
||||||
@synthesize totalContentLength = _totalContentLength;
|
@synthesize totalContentLength = _totalContentLength;
|
||||||
|
|
@ -150,12 +129,14 @@ NSString * AFCreateIncompleteDownloadDirectoryPath(void) {
|
||||||
if (![self hasAcceptableStatusCode]) {
|
if (![self hasAcceptableStatusCode]) {
|
||||||
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
|
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
|
||||||
[userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected status code in (%@), got %d", nil), AFStringFromIndexSet([[self class] 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.responseString forKey:NSLocalizedRecoverySuggestionErrorKey];
|
||||||
[userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey];
|
[userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey];
|
||||||
|
|
||||||
self.HTTPError = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo] autorelease];
|
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
|
} else if ([self.responseData length] > 0 && ![self hasAcceptableContentType]) { // Don't invalidate content type if there is no content
|
||||||
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
|
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
|
||||||
[userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected content type %@, got %@", nil), [[self class] 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.responseString forKey:NSLocalizedRecoverySuggestionErrorKey];
|
||||||
[userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey];
|
[userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey];
|
||||||
|
|
||||||
self.HTTPError = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo] autorelease];
|
self.HTTPError = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo] autorelease];
|
||||||
|
|
@ -188,7 +169,7 @@ NSString * AFCreateIncompleteDownloadDirectoryPath(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)hasAcceptableStatusCode {
|
- (BOOL)hasAcceptableStatusCode {
|
||||||
return ![[self class] acceptableStatusCodes] || [[[self class] acceptableStatusCodes] containsIndex:[self.response statusCode]];
|
return ![[self class] acceptableStatusCodes] || [[[self class] acceptableStatusCodes] containsIndex:(NSUInteger)[self.response statusCode]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)hasAcceptableContentType {
|
- (BOOL)hasAcceptableContentType {
|
||||||
|
|
@ -247,19 +228,6 @@ NSString * AFCreateIncompleteDownloadDirectoryPath(void) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
- (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
|
#pragma mark - AFHTTPRequestOperation
|
||||||
|
|
||||||
static id AFStaticClassValueImplementation(id self, SEL _cmd) {
|
static id AFStaticClassValueImplementation(id self, SEL _cmd) {
|
||||||
|
|
|
||||||
|
|
@ -161,9 +161,12 @@ static dispatch_queue_t image_request_operation_processing_queue() {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setImageScale:(CGFloat)imageScale {
|
- (void)setImageScale:(CGFloat)imageScale {
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wfloat-equal"
|
||||||
if (imageScale == _imageScale) {
|
if (imageScale == _imageScale) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
_imageScale = imageScale;
|
_imageScale = imageScale;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
#import "AFHTTPRequestOperation.h"
|
#import "AFHTTPRequestOperation.h"
|
||||||
|
|
||||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.25;
|
static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.17;
|
||||||
|
|
||||||
@interface AFNetworkActivityIndicatorManager ()
|
@interface AFNetworkActivityIndicatorManager ()
|
||||||
@property (readwrite, atomic, assign) NSInteger activityCount;
|
@property (readwrite, atomic, assign) NSInteger activityCount;
|
||||||
|
|
@ -33,6 +33,7 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.25;
|
||||||
@property (readonly, getter = isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;
|
@property (readonly, getter = isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;
|
||||||
|
|
||||||
- (void)updateNetworkActivityIndicatorVisibility;
|
- (void)updateNetworkActivityIndicatorVisibility;
|
||||||
|
- (void)updateNetworkActivityIndicatorVisibilityDelayed;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation AFNetworkActivityIndicatorManager
|
@implementation AFNetworkActivityIndicatorManager
|
||||||
|
|
@ -78,9 +79,9 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.25;
|
||||||
if (![self isNetworkActivityIndicatorVisible]) {
|
if (![self isNetworkActivityIndicatorVisible]) {
|
||||||
[self.activityIndicatorVisibilityTimer invalidate];
|
[self.activityIndicatorVisibilityTimer invalidate];
|
||||||
self.activityIndicatorVisibilityTimer = [NSTimer timerWithTimeInterval:kAFNetworkActivityIndicatorInvisibilityDelay target:self selector:@selector(updateNetworkActivityIndicatorVisibility) userInfo:nil repeats:NO];
|
self.activityIndicatorVisibilityTimer = [NSTimer timerWithTimeInterval:kAFNetworkActivityIndicatorInvisibilityDelay target:self selector:@selector(updateNetworkActivityIndicatorVisibility) userInfo:nil repeats:NO];
|
||||||
[[NSRunLoop currentRunLoop] addTimer:self.activityIndicatorVisibilityTimer forMode:NSRunLoopCommonModes];
|
[[NSRunLoop mainRunLoop] addTimer:self.activityIndicatorVisibilityTimer forMode:NSRunLoopCommonModes];
|
||||||
} else {
|
} else {
|
||||||
[self updateNetworkActivityIndicatorVisibility];
|
[self performSelectorOnMainThread:@selector(updateNetworkActivityIndicatorVisibility) withObject:nil waitUntilDone:NO modes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -90,9 +91,7 @@ static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateNetworkActivityIndicatorVisibility {
|
- (void)updateNetworkActivityIndicatorVisibility {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:[self isNetworkActivityIndicatorVisible]];
|
||||||
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:[self isNetworkActivityIndicatorVisible]];
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not exposed, but used if activityCount is set via KVC.
|
// Not exposed, but used if activityCount is set via KVC.
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,24 @@ extern NSString * const AFNetworkingOperationDidFinishNotification;
|
||||||
|
|
||||||
@warning Subclasses are strongly discouraged from overriding `setCompletionBlock:`, as `AFURLConnectionOperation`'s implementation includes a workaround to mitigate retain cycles, and what Apple rather ominously refers to as "The Deallocation Problem" (See http://developer.apple.com/library/ios/technotes/tn2109/_index.html#//apple_ref/doc/uid/DTS40010274-CH1-SUBSECTION11)
|
@warning Subclasses are strongly discouraged from overriding `setCompletionBlock:`, as `AFURLConnectionOperation`'s implementation includes a workaround to mitigate retain cycles, and what Apple rather ominously refers to as "The Deallocation Problem" (See http://developer.apple.com/library/ios/technotes/tn2109/_index.html#//apple_ref/doc/uid/DTS40010274-CH1-SUBSECTION11)
|
||||||
|
|
||||||
|
## NSCoding & NSCopying Conformance
|
||||||
|
|
||||||
|
`AFURLConnectionOperation` conforms to the `NSCoding` and `NSCopying` protocols, allowing operations to be archived to disk, and copied in memory, respectively. However, because of the intrinsic limitations of capturing the exact state of an operation at a particular moment, there are some important caveats to keep in mind:
|
||||||
|
|
||||||
|
### NSCoding Caveats
|
||||||
|
|
||||||
|
- Encoded operations do not include any block or stream properties. Be sure to set `completionBlock`, `outputStream`, and any callback blocks as necessary when using `-initWithCoder:` or `NSKeyedUnarchiver`.
|
||||||
|
- Operations are paused on `encodeWithCoder:`. If the operation was encoded while paused or still executing, its archived state will return `YES` for `isReady`. Otherwise, the state of an operation when encoding will remain unchanged.
|
||||||
|
|
||||||
|
### NSCopying Caveats
|
||||||
|
|
||||||
|
- `-copy` and `-copyWithZone:` return a new operation with the `NSURLRequest` of the original. So rather than an exact copy of the operation at that particular instant, the copying mechanism returns a completely new instance, which can be useful for retrying operations.
|
||||||
|
- A copy of an operation will not include the `outputStream` of the original.
|
||||||
|
- Operation copies do not include `completionBlock`. `completionBlock` often strongly captures a reference to `self`, which, perhaps surprisingly, would otherwise point to the _original_ operation when copied.
|
||||||
|
|
||||||
@warning Attempting to load a `file://` URL in iOS 4 may result in an `NSInvalidArgumentException`, caused by the connection returning `NSURLResponse` rather than `NSHTTPURLResponse`, which is the behavior as of iOS 5.
|
@warning Attempting to load a `file://` URL in iOS 4 may result in an `NSInvalidArgumentException`, caused by the connection returning `NSURLResponse` rather than `NSHTTPURLResponse`, which is the behavior as of iOS 5.
|
||||||
*/
|
*/
|
||||||
@interface AFURLConnectionOperation : NSOperation
|
@interface AFURLConnectionOperation : NSOperation <NSCoding, NSCopying>
|
||||||
|
|
||||||
///-------------------------------
|
///-------------------------------
|
||||||
/// @name Accessing Run Loop Modes
|
/// @name Accessing Run Loop Modes
|
||||||
|
|
@ -159,7 +174,7 @@ extern NSString * const AFNetworkingOperationDidFinishNotification;
|
||||||
/**
|
/**
|
||||||
Pauses the execution of the request operation.
|
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.
|
@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, cancelled, or paused operation has no effect.
|
||||||
*/
|
*/
|
||||||
- (void)pause;
|
- (void)pause;
|
||||||
|
|
||||||
|
|
@ -197,7 +212,9 @@ extern NSString * const AFNetworkingOperationDidFinishNotification;
|
||||||
/**
|
/**
|
||||||
Sets a callback to be called when an undetermined number of bytes have been uploaded to the server.
|
Sets a callback to be called when an undetermined number of bytes have been uploaded to the server.
|
||||||
|
|
||||||
@param block A block object to be called when an undetermined number of bytes have been uploaded to the server. This block has no return value and takes 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.
|
@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.
|
||||||
|
|
||||||
|
@discussion This block is called on the main thread.
|
||||||
|
|
||||||
@see setDownloadProgressBlock
|
@see setDownloadProgressBlock
|
||||||
*/
|
*/
|
||||||
|
|
@ -206,7 +223,7 @@ extern NSString * const AFNetworkingOperationDidFinishNotification;
|
||||||
/**
|
/**
|
||||||
Sets a callback to be called when an undetermined number of bytes have been downloaded from the server.
|
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.
|
@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.
|
||||||
|
|
||||||
@see setUploadProgressBlock
|
@see setUploadProgressBlock
|
||||||
*/
|
*/
|
||||||
|
|
@ -249,4 +266,38 @@ extern NSString * const AFNetworkingOperationDidFinishNotification;
|
||||||
*/
|
*/
|
||||||
- (void)setCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse))block;
|
- (void)setCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse))block;
|
||||||
|
|
||||||
|
///---------------------------------------
|
||||||
|
/// @name NSURLConnection Delegate Methods
|
||||||
|
/// @discussion NSURLConnection delegate methods were part of an informal protocol until iOS 5 & Mac OS 10.7, so the method signatures are declared here in order to allow subclasses to override these methods and call back to the super implementation.
|
||||||
|
///---------------------------------------
|
||||||
|
|
||||||
|
- (BOOL)connection:(NSURLConnection *)connection
|
||||||
|
canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace;
|
||||||
|
|
||||||
|
- (void)connection:(NSURLConnection *)connection
|
||||||
|
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
|
||||||
|
|
||||||
|
- (NSURLRequest *)connection:(NSURLConnection *)connection
|
||||||
|
willSendRequest:(NSURLRequest *)request
|
||||||
|
redirectResponse:(NSURLResponse *)redirectResponse;
|
||||||
|
|
||||||
|
- (void)connection:(NSURLConnection *)connection
|
||||||
|
didSendBodyData:(NSInteger)bytesWritten
|
||||||
|
totalBytesWritten:(NSInteger)totalBytesWritten
|
||||||
|
totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite;
|
||||||
|
|
||||||
|
- (void)connection:(NSURLConnection *)connection
|
||||||
|
didReceiveResponse:(NSURLResponse *)response;
|
||||||
|
|
||||||
|
- (void)connection:(NSURLConnection *)connection
|
||||||
|
didReceiveData:(NSData *)data;
|
||||||
|
|
||||||
|
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
|
||||||
|
|
||||||
|
- (void)connection:(NSURLConnection *)connection
|
||||||
|
didFailWithError:(NSError *)error;
|
||||||
|
|
||||||
|
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
|
||||||
|
willCacheResponse:(NSCachedURLResponse *)cachedResponse;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,10 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
AFHTTPOperationPausedState = -1,
|
AFOperationPausedState = -1,
|
||||||
AFHTTPOperationReadyState = 1,
|
AFOperationReadyState = 1,
|
||||||
AFHTTPOperationExecutingState = 2,
|
AFOperationExecutingState = 2,
|
||||||
AFHTTPOperationFinishedState = 3,
|
AFOperationFinishedState = 3,
|
||||||
} _AFOperationState;
|
} _AFOperationState;
|
||||||
|
|
||||||
typedef signed short AFOperationState;
|
typedef signed short AFOperationState;
|
||||||
|
|
@ -40,9 +40,6 @@ typedef UIBackgroundTaskIdentifier AFBackgroundTaskIdentifier;
|
||||||
typedef id AFBackgroundTaskIdentifier;
|
typedef id AFBackgroundTaskIdentifier;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static NSUInteger const kAFHTTPMinimumInitialDataCapacity = 1024;
|
|
||||||
static NSUInteger const kAFHTTPMaximumInitialDataCapacity = 1024 * 1024 * 8;
|
|
||||||
|
|
||||||
static NSString * const kAFNetworkingLockName = @"com.alamofire.networking.operation.lock";
|
static NSString * const kAFNetworkingLockName = @"com.alamofire.networking.operation.lock";
|
||||||
|
|
||||||
NSString * const AFNetworkingErrorDomain = @"com.alamofire.networking.error";
|
NSString * const AFNetworkingErrorDomain = @"com.alamofire.networking.error";
|
||||||
|
|
@ -58,13 +55,13 @@ typedef NSURLRequest * (^AFURLConnectionOperationRedirectResponseBlock)(NSURLCon
|
||||||
|
|
||||||
static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
|
static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AFHTTPOperationReadyState:
|
case AFOperationReadyState:
|
||||||
return @"isReady";
|
return @"isReady";
|
||||||
case AFHTTPOperationExecutingState:
|
case AFOperationExecutingState:
|
||||||
return @"isExecuting";
|
return @"isExecuting";
|
||||||
case AFHTTPOperationFinishedState:
|
case AFOperationFinishedState:
|
||||||
return @"isFinished";
|
return @"isFinished";
|
||||||
case AFHTTPOperationPausedState:
|
case AFOperationPausedState:
|
||||||
return @"isPaused";
|
return @"isPaused";
|
||||||
default:
|
default:
|
||||||
return @"state";
|
return @"state";
|
||||||
|
|
@ -73,28 +70,28 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
|
||||||
|
|
||||||
static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperationState toState, BOOL isCancelled) {
|
static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperationState toState, BOOL isCancelled) {
|
||||||
switch (fromState) {
|
switch (fromState) {
|
||||||
case AFHTTPOperationReadyState:
|
case AFOperationReadyState:
|
||||||
switch (toState) {
|
switch (toState) {
|
||||||
case AFHTTPOperationPausedState:
|
case AFOperationPausedState:
|
||||||
case AFHTTPOperationExecutingState:
|
case AFOperationExecutingState:
|
||||||
return YES;
|
return YES;
|
||||||
case AFHTTPOperationFinishedState:
|
case AFOperationFinishedState:
|
||||||
return isCancelled;
|
return isCancelled;
|
||||||
default:
|
default:
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
case AFHTTPOperationExecutingState:
|
case AFOperationExecutingState:
|
||||||
switch (toState) {
|
switch (toState) {
|
||||||
case AFHTTPOperationPausedState:
|
case AFOperationPausedState:
|
||||||
case AFHTTPOperationFinishedState:
|
case AFOperationFinishedState:
|
||||||
return YES;
|
return YES;
|
||||||
default:
|
default:
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
case AFHTTPOperationFinishedState:
|
case AFOperationFinishedState:
|
||||||
return NO;
|
return NO;
|
||||||
case AFHTTPOperationPausedState:
|
case AFOperationPausedState:
|
||||||
return toState == AFHTTPOperationReadyState;
|
return toState == AFOperationReadyState;
|
||||||
default:
|
default:
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
@ -121,6 +118,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
|
|
||||||
- (void)operationDidStart;
|
- (void)operationDidStart;
|
||||||
- (void)finish;
|
- (void)finish;
|
||||||
|
- (void)cancelConnection;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation AFURLConnectionOperation
|
@implementation AFURLConnectionOperation
|
||||||
|
|
@ -180,7 +178,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
|
|
||||||
self.outputStream = [NSOutputStream outputStreamToMemory];
|
self.outputStream = [NSOutputStream outputStreamToMemory];
|
||||||
|
|
||||||
self.state = AFHTTPOperationReadyState;
|
self.state = AFOperationReadyState;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
@ -326,10 +324,10 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
[self didChangeValueForKey:newStateKey];
|
[self didChangeValueForKey:newStateKey];
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AFHTTPOperationExecutingState:
|
case AFOperationExecutingState:
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidStartNotification object:self];
|
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidStartNotification object:self];
|
||||||
break;
|
break;
|
||||||
case AFHTTPOperationFinishedState:
|
case AFOperationFinishedState:
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
|
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -355,20 +353,24 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)pause {
|
- (void)pause {
|
||||||
if ([self isPaused]) {
|
if ([self isPaused] || [self isFinished] || [self isCancelled]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self.lock lock];
|
[self.lock lock];
|
||||||
self.state = AFHTTPOperationPausedState;
|
|
||||||
|
|
||||||
[self.connection performSelector:@selector(cancel) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
|
if ([self isExecuting]) {
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
|
[self.connection performSelector:@selector(cancel) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
self.state = AFOperationPausedState;
|
||||||
|
|
||||||
[self.lock unlock];
|
[self.lock unlock];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isPaused {
|
- (BOOL)isPaused {
|
||||||
return self.state == AFHTTPOperationPausedState;
|
return self.state == AFOperationPausedState;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)resume {
|
- (void)resume {
|
||||||
|
|
@ -377,7 +379,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
}
|
}
|
||||||
|
|
||||||
[self.lock lock];
|
[self.lock lock];
|
||||||
self.state = AFHTTPOperationReadyState;
|
self.state = AFOperationReadyState;
|
||||||
|
|
||||||
[self start];
|
[self start];
|
||||||
[self.lock unlock];
|
[self.lock unlock];
|
||||||
|
|
@ -386,15 +388,15 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
#pragma mark - NSOperation
|
#pragma mark - NSOperation
|
||||||
|
|
||||||
- (BOOL)isReady {
|
- (BOOL)isReady {
|
||||||
return self.state == AFHTTPOperationReadyState && [super isReady];
|
return self.state == AFOperationReadyState && [super isReady];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isExecuting {
|
- (BOOL)isExecuting {
|
||||||
return self.state == AFHTTPOperationExecutingState;
|
return self.state == AFOperationExecutingState;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isFinished {
|
- (BOOL)isFinished {
|
||||||
return self.state == AFHTTPOperationFinishedState;
|
return self.state == AFOperationFinishedState;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isConcurrent {
|
- (BOOL)isConcurrent {
|
||||||
|
|
@ -404,7 +406,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
- (void)start {
|
- (void)start {
|
||||||
[self.lock lock];
|
[self.lock lock];
|
||||||
if ([self isReady]) {
|
if ([self isReady]) {
|
||||||
self.state = AFHTTPOperationExecutingState;
|
self.state = AFOperationExecutingState;
|
||||||
|
|
||||||
[self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
|
[self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
|
||||||
}
|
}
|
||||||
|
|
@ -430,7 +432,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)finish {
|
- (void)finish {
|
||||||
self.state = AFHTTPOperationFinishedState;
|
self.state = AFOperationFinishedState;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)cancel {
|
- (void)cancel {
|
||||||
|
|
@ -520,7 +522,7 @@ didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
|
||||||
|
|
||||||
- (NSURLRequest *)connection:(NSURLConnection *)connection
|
- (NSURLRequest *)connection:(NSURLConnection *)connection
|
||||||
willSendRequest:(NSURLRequest *)request
|
willSendRequest:(NSURLRequest *)request
|
||||||
redirectResponse:(NSURLResponse *)redirectResponse;
|
redirectResponse:(NSURLResponse *)redirectResponse
|
||||||
{
|
{
|
||||||
if (self.redirectResponse) {
|
if (self.redirectResponse) {
|
||||||
return self.redirectResponse(connection, request, redirectResponse);
|
return self.redirectResponse(connection, request, redirectResponse);
|
||||||
|
|
@ -535,7 +537,9 @@ didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
|
||||||
totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
|
totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
|
||||||
{
|
{
|
||||||
if (self.uploadProgress) {
|
if (self.uploadProgress) {
|
||||||
self.uploadProgress(bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
self.uploadProgress(bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -558,7 +562,9 @@ didReceiveResponse:(NSURLResponse *)response
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.downloadProgress) {
|
if (self.downloadProgress) {
|
||||||
self.downloadProgress((long long)[data length], self.totalBytesRead, self.response.expectedContentLength);
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
self.downloadProgress((long long)[data length], self.totalBytesRead, self.response.expectedContentLength);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -598,4 +604,61 @@ didReceiveResponse:(NSURLResponse *)response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - NSCoding
|
||||||
|
|
||||||
|
- (id)initWithCoder:(NSCoder *)aDecoder {
|
||||||
|
NSURLRequest *request = [aDecoder decodeObjectForKey:@"request"];
|
||||||
|
|
||||||
|
self = [self initWithRequest:request];
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.state = [aDecoder decodeIntegerForKey:@"state"];
|
||||||
|
self.cancelled = [aDecoder decodeBoolForKey:@"isCancelled"];
|
||||||
|
self.response = [aDecoder decodeObjectForKey:@"response"];
|
||||||
|
self.error = [aDecoder decodeObjectForKey:@"error"];
|
||||||
|
self.responseData = [aDecoder decodeObjectForKey:@"responseData"];
|
||||||
|
self.totalBytesRead = [[aDecoder decodeObjectForKey:@"totalBytesRead"] longLongValue];
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||||
|
[self pause];
|
||||||
|
|
||||||
|
[aCoder encodeObject:self.request forKey:@"request"];
|
||||||
|
|
||||||
|
switch (self.state) {
|
||||||
|
case AFOperationExecutingState:
|
||||||
|
case AFOperationPausedState:
|
||||||
|
[aCoder encodeInteger:AFOperationReadyState forKey:@"state"];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
[aCoder encodeInteger:self.state forKey:@"state"];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
[aCoder encodeBool:[self isCancelled] forKey:@"isCancelled"];
|
||||||
|
[aCoder encodeObject:self.response forKey:@"response"];
|
||||||
|
[aCoder encodeObject:self.error forKey:@"error"];
|
||||||
|
[aCoder encodeObject:self.responseData forKey:@"responseData"];
|
||||||
|
[aCoder encodeObject:[NSNumber numberWithLongLong:self.totalBytesRead] forKey:@"totalBytesRead"];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - NSCopying
|
||||||
|
|
||||||
|
- (id)copyWithZone:(NSZone *)zone {
|
||||||
|
AFURLConnectionOperation *operation = [[[self class] allocWithZone:zone] initWithRequest:self.request];
|
||||||
|
|
||||||
|
operation.uploadProgress = self.uploadProgress;
|
||||||
|
operation.downloadProgress = self.downloadProgress;
|
||||||
|
operation.authenticationAgainstProtectionSpace = self.authenticationAgainstProtectionSpace;
|
||||||
|
operation.authenticationChallenge = self.authenticationChallenge;
|
||||||
|
operation.cacheResponse = self.cacheResponse;
|
||||||
|
operation.redirectResponse = self.redirectResponse;
|
||||||
|
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,10 @@ static char kAFImageRequestOperationObjectKey;
|
||||||
- (void)setImageWithURL:(NSURL *)url
|
- (void)setImageWithURL:(NSURL *)url
|
||||||
placeholderImage:(UIImage *)placeholderImage
|
placeholderImage:(UIImage *)placeholderImage
|
||||||
{
|
{
|
||||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
|
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
|
||||||
[request setHTTPShouldHandleCookies:NO];
|
[request setHTTPShouldHandleCookies:NO];
|
||||||
[request setHTTPShouldUsePipelining:YES];
|
[request setHTTPShouldUsePipelining:YES];
|
||||||
|
[request addValue:@"image/*" forHTTPHeaderField:@"Accept"];
|
||||||
|
|
||||||
[self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil failure:nil];
|
[self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil failure:nil];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -193,8 +193,8 @@
|
||||||
children = (
|
children = (
|
||||||
F8DA09E31396AC040057D0CC /* main.m */,
|
F8DA09E31396AC040057D0CC /* main.m */,
|
||||||
F8129C3815910830009BFE23 /* Prefix.pch */,
|
F8129C3815910830009BFE23 /* Prefix.pch */,
|
||||||
F8129C7215910C37009BFE23 /* AppDelegate.m */,
|
|
||||||
F8129C7315910C37009BFE23 /* AppDelegate.h */,
|
F8129C7315910C37009BFE23 /* AppDelegate.h */,
|
||||||
|
F8129C7215910C37009BFE23 /* AppDelegate.m */,
|
||||||
F8E4696C1395739D00DB05C8 /* iOS-Info.plist */,
|
F8E4696C1395739D00DB05C8 /* iOS-Info.plist */,
|
||||||
);
|
);
|
||||||
name = "Supporting Files";
|
name = "Supporting Files";
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,11 @@ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||||
|
|
||||||
[self.window makeKeyAndOrderFront:self];
|
[self.window makeKeyAndOrderFront:self];
|
||||||
|
|
||||||
[Tweet publicTimelineTweetsWithBlock:^(NSArray *tweets) {
|
[Tweet publicTimelineTweetsWithBlock:^(NSArray *tweets, NSError *error) {
|
||||||
|
if (error) {
|
||||||
|
[[NSAlert alertWithMessageText:NSLocalizedString(@"Error", nil) defaultButton:NSLocalizedString(@"OK", nil) alternateButton:nil otherButton:nil informativeTextWithFormat:@"%@",[error localizedDescription]] runModal];
|
||||||
|
}
|
||||||
|
|
||||||
self.tweetsArrayController.content = tweets;
|
self.tweetsArrayController.content = tweets;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,10 @@
|
||||||
[_activityIndicatorView startAnimating];
|
[_activityIndicatorView startAnimating];
|
||||||
self.navigationItem.rightBarButtonItem.enabled = NO;
|
self.navigationItem.rightBarButtonItem.enabled = NO;
|
||||||
|
|
||||||
[Tweet publicTimelineTweetsWithBlock:^(NSArray *tweets) {
|
[Tweet publicTimelineTweetsWithBlock:^(NSArray *tweets, NSError *error) {
|
||||||
if (tweets) {
|
if (error) {
|
||||||
|
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil) message:[error localizedDescription] delegate:nil cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(@"OK", nil), nil] show];
|
||||||
|
} else {
|
||||||
_tweets = tweets;
|
_tweets = tweets;
|
||||||
[self.tableView reloadData];
|
[self.tableView reloadData];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,6 @@
|
||||||
|
|
||||||
- (id)initWithAttributes:(NSDictionary *)attributes;
|
- (id)initWithAttributes:(NSDictionary *)attributes;
|
||||||
|
|
||||||
+ (void)publicTimelineTweetsWithBlock:(void (^)(NSArray *tweets))block;
|
+ (void)publicTimelineTweetsWithBlock:(void (^)(NSArray *tweets, NSError *error))block;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
+ (void)publicTimelineTweetsWithBlock:(void (^)(NSArray *tweets))block {
|
+ (void)publicTimelineTweetsWithBlock:(void (^)(NSArray *tweets, NSError *error))block {
|
||||||
[[AFTwitterAPIClient sharedClient] getPath:@"statuses/public_timeline.json" parameters:[NSDictionary dictionaryWithObject:@"false" forKey:@"include_entities"] success:^(AFHTTPRequestOperation *operation, id JSON) {
|
[[AFTwitterAPIClient sharedClient] getPath:@"statuses/public_timeline.json" parameters:[NSDictionary dictionaryWithObject:@"false" forKey:@"include_entities"] success:^(AFHTTPRequestOperation *operation, id JSON) {
|
||||||
NSMutableArray *mutableTweets = [NSMutableArray arrayWithCapacity:[JSON count]];
|
NSMutableArray *mutableTweets = [NSMutableArray arrayWithCapacity:[JSON count]];
|
||||||
for (NSDictionary *attributes in JSON) {
|
for (NSDictionary *attributes in JSON) {
|
||||||
|
|
@ -61,16 +61,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block) {
|
if (block) {
|
||||||
block([NSArray arrayWithArray:mutableTweets]);
|
block([NSArray arrayWithArray:mutableTweets], nil);
|
||||||
}
|
}
|
||||||
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
|
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
|
||||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
|
||||||
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil) message:[error localizedDescription] delegate:nil cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(@"OK", nil), nil] show];
|
|
||||||
#else
|
|
||||||
[[NSAlert alertWithMessageText:NSLocalizedString(@"Error", nil) defaultButton:NSLocalizedString(@"OK", nil) alternateButton:nil otherButton:nil informativeTextWithFormat:[error localizedDescription]] runModal];
|
|
||||||
#endif
|
|
||||||
if (block) {
|
if (block) {
|
||||||
block(nil);
|
block([NSArray array], error);
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,9 @@
|
||||||
NSString * const kUserProfileImageDidLoadNotification = @"com.alamofire.user.profile-image.loaded";
|
NSString * const kUserProfileImageDidLoadNotification = @"com.alamofire.user.profile-image.loaded";
|
||||||
|
|
||||||
@interface User ()
|
@interface User ()
|
||||||
|
#if __MAC_OS_X_VERSION_MIN_REQUIRED
|
||||||
+ (NSOperationQueue *)sharedProfileImageRequestOperationQueue;
|
+ (NSOperationQueue *)sharedProfileImageRequestOperationQueue;
|
||||||
|
#endif
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation User {
|
@implementation User {
|
||||||
|
|
|
||||||
|
|
@ -75,11 +75,11 @@ AFNetworking is architected to be as small and modular as possible, in order to
|
||||||
<tr><th colspan="2" style="text-align:center;">Images</th></tr>
|
<tr><th colspan="2" style="text-align:center;">Images</th></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="http://afnetworking.org/Documentation/Classes/AFImageRequestOperation.html">AFImageRequestOperation</a></td>
|
<td><a href="http://afnetworking.org/Documentation/Classes/AFImageRequestOperation.html">AFImageRequestOperation</a></td>
|
||||||
<td>A subclass of <tt>AFHTTPRequestOperation</tt> for downloading an processing images.</td>
|
<td>A subclass of <tt>AFHTTPRequestOperation</tt> for downloading and processing images.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="http://afnetworking.org/Documentation/Categories/UIImageView+AFNetworking.html">UIImageView+AFNetworking</a></td>
|
<td><a href="http://afnetworking.org/Documentation/Categories/UIImageView+AFNetworking.html">UIImageView+AFNetworking</a></td>
|
||||||
<td>Adds methods to `UIImageView` for loading remote images asynchronously from a URL.</td>
|
<td>Adds methods to <tt>UIImageView</tt> for loading remote images asynchronously from a URL.</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
@ -124,8 +124,8 @@ NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:@"POST
|
||||||
}];
|
}];
|
||||||
|
|
||||||
AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease];
|
AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease];
|
||||||
[operation setUploadProgressBlock:^(NSInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) {
|
[operation setUploadProgressBlock:^(NSInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
|
||||||
NSLog(@"Sent %d of %d bytes", totalBytesWritten, totalBytesExpectedToWrite);
|
NSLog(@"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
|
||||||
}];
|
}];
|
||||||
[operation start];
|
[operation start];
|
||||||
```
|
```
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue