Skip to content
Browse files

Merge remote-tracking branch 'upstream/master' into develop

  • Loading branch information...
2 parents 3090f2d + 84abd71 commit dfeffc54eb57b30a2a42f5f33663ede2f05164c2 @flambert committed
View
8 AFNetworking/AFHTTPClient.h
@@ -124,8 +124,14 @@ extern NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *paramete
[NSURL URLWithString:@"/foo/" relativeToURL:baseURL]; // http://example.com/foo/
[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
View
48 AFNetworking/AFHTTPClient.m
@@ -254,6 +254,11 @@ - (id)initWithBaseURL:(NSURL *)url {
return nil;
}
+ // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected
+ if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
+ url = [url URLByAppendingPathComponent:@""];
+ }
+
self.baseURL = url;
self.stringEncoding = NSUTF8StringEncoding;
@@ -659,6 +664,47 @@ - (void)patchPath:(NSString *)path
[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
#pragma mark -
@@ -720,7 +766,7 @@ - (id)initWithURLRequest:(NSMutableURLRequest *)request
self.request = request;
self.stringEncoding = encoding;
- self.temporaryFilePath = [AFMultipartTemporaryFileDirectoryPath() stringByAppendingPathComponent:[NSString stringWithFormat:@"%lu", (long)[[self.request URL] hash]]];
+ self.temporaryFilePath = [AFMultipartTemporaryFileDirectoryPath() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
self.outputStream = [NSOutputStream outputStreamToFileAtPath:self.temporaryFilePath append:NO];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
View
2 AFNetworking/AFHTTPRequestOperation.m
@@ -129,12 +129,14 @@ - (NSError *)error {
if (![self hasAcceptableStatusCode]) {
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:self.responseString forKey:NSLocalizedRecoverySuggestionErrorKey];
[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 class] acceptableContentTypes], [self.response MIMEType]] forKey:NSLocalizedDescriptionKey];
+ [userInfo setValue:self.responseString forKey:NSLocalizedRecoverySuggestionErrorKey];
[userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey];
self.HTTPError = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo] autorelease];
View
17 AFNetworking/AFURLConnectionOperation.h
@@ -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)
+ ## 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.
*/
-@interface AFURLConnectionOperation : NSOperation
+@interface AFURLConnectionOperation : NSOperation <NSCoding, NSCopying>
///-------------------------------
/// @name Accessing Run Loop Modes
View
119 AFNetworking/AFURLConnectionOperation.m
@@ -26,10 +26,10 @@
#endif
typedef enum {
- AFHTTPOperationPausedState = -1,
- AFHTTPOperationReadyState = 1,
- AFHTTPOperationExecutingState = 2,
- AFHTTPOperationFinishedState = 3,
+ AFOperationPausedState = -1,
+ AFOperationReadyState = 1,
+ AFOperationExecutingState = 2,
+ AFOperationFinishedState = 3,
} _AFOperationState;
typedef signed short AFOperationState;
@@ -40,9 +40,6 @@
typedef id AFBackgroundTaskIdentifier;
#endif
-static NSUInteger const kAFHTTPMinimumInitialDataCapacity = 1024;
-static NSUInteger const kAFHTTPMaximumInitialDataCapacity = 1024 * 1024 * 8;
-
static NSString * const kAFNetworkingLockName = @"com.alamofire.networking.operation.lock";
NSString * const AFNetworkingErrorDomain = @"com.alamofire.networking.error";
@@ -58,13 +55,13 @@
static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
switch (state) {
- case AFHTTPOperationReadyState:
+ case AFOperationReadyState:
return @"isReady";
- case AFHTTPOperationExecutingState:
+ case AFOperationExecutingState:
return @"isExecuting";
- case AFHTTPOperationFinishedState:
+ case AFOperationFinishedState:
return @"isFinished";
- case AFHTTPOperationPausedState:
+ case AFOperationPausedState:
return @"isPaused";
default:
return @"state";
@@ -73,28 +70,28 @@
static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperationState toState, BOOL isCancelled) {
switch (fromState) {
- case AFHTTPOperationReadyState:
+ case AFOperationReadyState:
switch (toState) {
- case AFHTTPOperationPausedState:
- case AFHTTPOperationExecutingState:
+ case AFOperationPausedState:
+ case AFOperationExecutingState:
return YES;
- case AFHTTPOperationFinishedState:
+ case AFOperationFinishedState:
return isCancelled;
default:
return NO;
}
- case AFHTTPOperationExecutingState:
+ case AFOperationExecutingState:
switch (toState) {
- case AFHTTPOperationPausedState:
- case AFHTTPOperationFinishedState:
+ case AFOperationPausedState:
+ case AFOperationFinishedState:
return YES;
default:
return NO;
}
- case AFHTTPOperationFinishedState:
+ case AFOperationFinishedState:
return NO;
- case AFHTTPOperationPausedState:
- return toState == AFHTTPOperationReadyState;
+ case AFOperationPausedState:
+ return toState == AFOperationReadyState;
default:
return YES;
}
@@ -121,6 +118,7 @@ @interface AFURLConnectionOperation ()
- (void)operationDidStart;
- (void)finish;
+- (void)cancelConnection;
@end
@implementation AFURLConnectionOperation
@@ -180,7 +178,7 @@ - (id)initWithRequest:(NSURLRequest *)urlRequest {
self.outputStream = [NSOutputStream outputStreamToMemory];
- self.state = AFHTTPOperationReadyState;
+ self.state = AFOperationReadyState;
return self;
}
@@ -326,10 +324,10 @@ - (void)setState:(AFOperationState)state {
[self didChangeValueForKey:newStateKey];
switch (state) {
- case AFHTTPOperationExecutingState:
+ case AFOperationExecutingState:
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidStartNotification object:self];
break;
- case AFHTTPOperationFinishedState:
+ case AFOperationFinishedState:
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
break;
default:
@@ -366,13 +364,13 @@ - (void)pause {
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
}
- self.state = AFHTTPOperationPausedState;
+ self.state = AFOperationPausedState;
[self.lock unlock];
}
- (BOOL)isPaused {
- return self.state == AFHTTPOperationPausedState;
+ return self.state == AFOperationPausedState;
}
- (void)resume {
@@ -381,7 +379,7 @@ - (void)resume {
}
[self.lock lock];
- self.state = AFHTTPOperationReadyState;
+ self.state = AFOperationReadyState;
[self start];
[self.lock unlock];
@@ -390,15 +388,15 @@ - (void)resume {
#pragma mark - NSOperation
- (BOOL)isReady {
- return self.state == AFHTTPOperationReadyState && [super isReady];
+ return self.state == AFOperationReadyState && [super isReady];
}
- (BOOL)isExecuting {
- return self.state == AFHTTPOperationExecutingState;
+ return self.state == AFOperationExecutingState;
}
- (BOOL)isFinished {
- return self.state == AFHTTPOperationFinishedState;
+ return self.state == AFOperationFinishedState;
}
- (BOOL)isConcurrent {
@@ -408,7 +406,7 @@ - (BOOL)isConcurrent {
- (void)start {
[self.lock lock];
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]];
}
@@ -434,7 +432,7 @@ - (void)operationDidStart {
}
- (void)finish {
- self.state = AFHTTPOperationFinishedState;
+ self.state = AFOperationFinishedState;
}
- (void)cancel {
@@ -606,4 +604,61 @@ - (NSCachedURLResponse *)connection:(NSURLConnection *)connection
}
}
+#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
View
3 AFNetworking/UIImageView+AFNetworking.m
@@ -101,9 +101,10 @@ - (void)setImageWithURL:(NSURL *)url
imageProcessingBlock:(UIImage *(^)(UIImage *image))imageProcessingBlock
cacheName:(NSString *)cacheNameOrNil
{
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
+ NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPShouldHandleCookies:NO];
[request setHTTPShouldUsePipelining:YES];
+ [request addValue:@"image/*" forHTTPHeaderField:@"Accept"];
[self setImageWithURLRequest:request placeholderImage:placeholderImage imageProcessingBlock:imageProcessingBlock cacheName:cacheNameOrNil success:nil failure:nil];
}
View
2 Example/AFNetworking iOS Example.xcodeproj/project.pbxproj
@@ -189,8 +189,8 @@
children = (
F8DA09E31396AC040057D0CC /* main.m */,
F8129C3815910830009BFE23 /* Prefix.pch */,
- F8129C7215910C37009BFE23 /* AppDelegate.m */,
F8129C7315910C37009BFE23 /* AppDelegate.h */,
+ F8129C7215910C37009BFE23 /* AppDelegate.m */,
F8E4696C1395739D00DB05C8 /* iOS-Info.plist */,
);
name = "Supporting Files";
View
6 Example/AppDelegate.m
@@ -71,7 +71,11 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification {
[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;
}];
View
6 Example/Classes/Controllers/PublicTimelineViewController.m
@@ -41,8 +41,10 @@ - (void)reload:(id)sender {
[_activityIndicatorView startAnimating];
self.navigationItem.rightBarButtonItem.enabled = NO;
- [Tweet publicTimelineTweetsWithBlock:^(NSArray *tweets) {
- if (tweets) {
+ [Tweet publicTimelineTweetsWithBlock:^(NSArray *tweets, NSError *error) {
+ if (error) {
+ [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil) message:[error localizedDescription] delegate:nil cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(@"OK", nil), nil] show];
+ } else {
_tweets = tweets;
[self.tableView reloadData];
}
View
2 Example/Classes/Models/Tweet.h
@@ -33,6 +33,6 @@
- (id)initWithAttributes:(NSDictionary *)attributes;
-+ (void)publicTimelineTweetsWithBlock:(void (^)(NSArray *tweets))block;
++ (void)publicTimelineTweetsWithBlock:(void (^)(NSArray *tweets, NSError *error))block;
@end
View
13 Example/Classes/Models/Tweet.m
@@ -52,7 +52,7 @@ - (id)initWithAttributes:(NSDictionary *)attributes {
#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) {
NSMutableArray *mutableTweets = [NSMutableArray arrayWithCapacity:[JSON count]];
for (NSDictionary *attributes in JSON) {
@@ -61,16 +61,11 @@ + (void)publicTimelineTweetsWithBlock:(void (^)(NSArray *tweets))block {
}
if (block) {
- block([NSArray arrayWithArray:mutableTweets]);
+ block([NSArray arrayWithArray:mutableTweets], nil);
}
- } 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
+ } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (block) {
- block(nil);
+ block([NSArray array], error);
}
}];
}

0 comments on commit dfeffc5

Please sign in to comment.
Something went wrong with that request. Please try again.