Last active
August 29, 2015 14:06
-
-
Save chrishulbert/35ecbec4b37d36b0d608 to your computer and use it in GitHub Desktop.
Better solution here: http://www.splinter.com.au/2014/09/10/afnetworking-error-bodies/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!!! There's a better solution here now, that doesn't require swizzling: | |
!!! http://www.splinter.com.au/2014/09/10/afnetworking-error-bodies/ | |
!!! But i'll leave the below swizzling solution up for old time's sake | |
// AFURLSessionManager+ErrorResponse.h | |
// This hacks AFURLSessionManager so that it returns the error response in failure callbacks, in the error's userInfo. | |
// Usage: | |
// [mySessionManager POST:@"some_api_endpoint" parameters:params success:^(NSURLSessionDataTask *task, NSDictionary *responseObject) { | |
// ... | |
// } failure:^(NSURLSessionDataTask *task, NSError *error) { | |
// id responseObject = error.userInfo[kErrorResponseObjectKey]; | |
// ... | |
// }]; | |
#import "AFURLSessionManager.h" | |
/// The NSError userInfo dictionary key for the responseObject. | |
#define kErrorResponseObjectKey @"kErrorResponseObjectKey" | |
@interface AFURLSessionManager (ErrorResponse) | |
@end | |
// AFURLSessionManager+ErrorResponse.m | |
#import "AFURLSessionManager+ErrorResponse.h" | |
#import <objc/runtime.h> | |
@implementation AFURLSessionManager (ErrorResponse) | |
#pragma mark - Hooks into the VC lifecycle | |
/// Wrap the completion handler with a new handler that injects the response into an error's userInfo before calling the original handler. | |
- (NSURLSessionDataTask *)errorResponse_dataTaskWithRequest:(NSURLRequest *)request | |
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))originalCompletionHandler { | |
// This calls through to the original, really. | |
return [self errorResponse_dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { | |
// If there's an error, store the response in it if we've got one. | |
if (error && responseObject) { | |
if (error.userInfo) { // Already has a dictionary, so we need to add to it. | |
NSMutableDictionary *userInfo = [error.userInfo mutableCopy]; | |
userInfo[kErrorResponseObjectKey] = responseObject; | |
error = [NSError errorWithDomain:error.domain code:error.code userInfo:[userInfo copy]]; | |
} else { // No dictionary, make a new one. | |
error = [NSError errorWithDomain:error.domain code:error.code userInfo:@{kErrorResponseObjectKey: responseObject}]; | |
} | |
} | |
// Call the original handler. | |
if (originalCompletionHandler) { | |
originalCompletionHandler(response, responseObject, error); | |
} | |
}]; | |
} | |
#pragma mark - Swizzling | |
/// Do the swizzling at load time. | |
+ (void)load { | |
ErrorResponse_MethodSwizzle(self, @selector(dataTaskWithRequest:completionHandler:), @selector(errorResponse_dataTaskWithRequest:completionHandler:)); | |
} | |
/// Swizzle the method into place. | |
void ErrorResponse_MethodSwizzle(Class c, SEL origSEL, SEL overrideSEL) { | |
Method origMethod = class_getInstanceMethod(c, origSEL); | |
Method overrideMethod = class_getInstanceMethod(c, overrideSEL); | |
if (class_addMethod(c, origSEL, method_getImplementation(overrideMethod), method_getTypeEncoding(overrideMethod))) { | |
class_replaceMethod(c, overrideSEL, method_getImplementation(origMethod), method_getTypeEncoding(origMethod)); | |
} else { | |
method_exchangeImplementations(origMethod, overrideMethod); | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment