AFHTTPSessionManager – 获取反序列化/原始响应体(NSData?)

我根据推荐的iOS 8最佳实践(代替之前使用的AFHTTPOperationManager)将AFHTTPSessionManager子类化。

我可以从task获取NSHTTPURLResponse (除了没有正文,只有标题),并且回调返回序列化的responseObject ,这很好。

有时我需要将响应记录为字符串或将其显示在文本字段中 – 似乎没有办法使用SessionManager本地执行此操作? OperationManager允许您将原始响应引用为NSString:

 operation.responseString; 

我想我可以对序列化的requestObject进行字符串化,但这似乎有很多不必要的开销,并且如果响应对象是无效的JSON则无济于事。

这是我的子类单例:

 @implementation MyAFHTTPSessionManager + (instancetype)sharedManager { static id instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[self alloc] init]; }); return instance; } 

然后做一个简单的GET(我已经添加到块方法中),我可以这样做:

 [[MyAFHTTPSessionManager sharedManager] GET:_url parameters:queryParams success:^(NSURLSessionDataTask *task, id responseObject) { completion(YES, task, responseObject, nil); } failure:^(NSURLSessionDataTask *task, NSError *error) { completion(NO, task, nil, error); }]; 

您可以通过创建自定义响应序列化程序来完成此操作,该序列化程序使用标准响应序列化程序记录数据并序列化响应,将原始数据和已解析对象组合到自定义复合响应对象中。

 @interface ResponseWithRawData : NSObject @property (nonatomic, retain) NSData *data; @property (nonatomic, retain) id object; @end @interface ResponseSerializerWithRawData : NSObject  - (instancetype)initWithForwardingSerializer:(id)forwardingSerializer; @end ... @implementation ResponseWithRawData @end @interface ResponseSerializerWithRawData () @property (nonatomic, retain) forwardingSerializer; @end @implementation ResponseSerializerWithRawData - (instancetype)initWithForwardingSerializer:(id)forwardingSerializer { self = [super init]; if (self) { self.forwardingSerializer = forwardingSerializer; } return self; } - (id)responseObjectForResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError *__autoreleasing *)error { id object = [self.forwardingSerializer responseObjectForResponse:response data:data error:error]; // TODO: could just log the data here and then return object; so that none of the request handlers have to change if (*error) { // TODO: Create a new NSError object and add the data to the "userInfo" // TODO: OR ignore the error and return the response object with the raw data only return nil; } else { ResponseWithRawData *response = [[ResponseWithRawData alloc] init]; response.data = data; response.object = object; return response; } } @end 

然后在会话管理器上设置此序列化程序:

 @implementation MyAFHTTPSessionManager + (instancetype)sharedManager { static id instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[self alloc] init]; instance.responseSerializer = [[ResponseSerializerWithRawData alloc] initWithForwardingSerializer:instance.responseSerializer]; }); return instance; } 

现在在您的完成处理程序中,您将获得ResponseWithRawData的实例:

 [[MyAFHTTPSessionManager sharedManager] GET:_url parameters:queryParams success:^(NSURLSessionDataTask *task, id responseObject) { ResponseWithRawData *responseWithRawData = responseObject; NSLog(@"raw data: %@", responseWithRawData.data); // If UTF8 NSLog(@"raw data: %@", [[NSString alloc] initWithData:responseWithRawData.data encoding:NSUTF8StringEncoding]); // TODO: do something with parsed object } failure:^(NSURLSessionDataTask *task, NSError *error) { }]; 

我只是在没有编译/测试的情况下掀起了这个,所以我会留给你调试并填补空白。

您可以使用“AFNetworkingOperationFailingURLResponseDataErrorKey”键直接从AFNetworking访问“数据”对象,因此不需要对AFJSONResponseSerializer进行子类化。 您可以将数据序列化为可读字典。 以下是获取JSON数据的示例代码:

 NSData *errorData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey]; NSDictionary *serializedData = [NSJSONSerialization JSONObjectWithData: errorData options:kNilOptions error:nil]; 

以下是在Failur块中获取状态代码的代码

 NSHTTPURLResponse* r = (NSHTTPURLResponse*)task.response; NSLog( @"success: %d", r.statusCode );