我一直在我的应用中使用AFNetworking 2.0。 我注意到,如果我的网络服务返回500状态代码,我就不会得到响应的主体。
以下是我的PHP代码
的示例try
{
$conn = new PDO( "sqlsrv:server=$serverName;Database = $database", $uid, $pwd);
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
return $conn;
}
catch( PDOException $e )
{
$response->status(500);
echo( "Connection Error: " . $e->getMessage() );
}
如果我使用一个简单的休息客户端,这是一个响应体的例子。
Connection Error: SQLSTATE[08001]: [Microsoft][SQL Server Native Client 11.0]SQL Server Network Interfaces: Error Locating Server/Instance Specified [xFFFFFFFF].
然而,这似乎是我从AFNetworking获得的唯一回应
Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x15e58fa0 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
这是我的Objective-c代码的一部分。
...} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"%@",error.description);
}];
有没有办法可以获得回复正文?
编辑:更多代码以澄清
以下是我的AFHTTPSessionManager
子类的一部分@implementation MSMAMobileAPIClient
+ (MSMAMobileAPIClient *)sharedClient {
static MSMAMobileAPIClient *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[MSMAMobileAPIClient alloc] initWithDefaultURL];
});
return _sharedClient;
}
- (id)initWithDefaultURL {
return [self initWithBaseURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://%@/mamobile/index.php/" ,[[NSUserDefaults standardUserDefaults] stringForKey:@"serviceIPAddress"]]]];
}
- (id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (!self) {
return nil;
}
self.responseSerializer = [AFCompoundResponseSerializer compoundSerializerWithResponseSerializers:@[[AFJSONResponseSerializer serializer], [AFHTTPResponseSerializer serializer]]];
return self;
}
我尝试将响应序列化程序设置为AFCompoundResponseSerializer但它似乎没有什么区别
以下是我称之为图书馆员的子类示例。
-(void)searchForItemWithString:(NSString *)searchString withCompletionBlock:(arrayBlock)block {
self.inventorySearchBlock = block;
NSDictionary *parameters = @{@"query": searchString};
[[MSMAMobileAPIClient sharedClient] GET:@"inventory/search" parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {
if (!responseObject) {
NSLog(@"Error parsing JSON");
} else {
//do stuff with the json dictionary that's returned..
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"Error: %@",error.description);
}];
}
答案 0 :(得分:14)
更新:我创建了一个github存储库来包含我正在使用的最新代码。所有更改都将在那里发布。 https://github.com/Hackmodford/HMFJSONResponseSerializerWithData
答案来自github上的这个问题。 https://github.com/AFNetworking/AFNetworking/issues/1397
gfiumara是想出这个的开发者。我只是稍微修改了他的AFJSONResponseSerializer的子类,以包含一个实际的字符串而不是NSData//MSJSONResponseSerializerWithData.h
#import "AFURLResponseSerialization.h"
/// NSError userInfo key that will contain response data
static NSString * const JSONResponseSerializerWithDataKey = @"JSONResponseSerializerWithDataKey";
@interface MSJSONResponseSerializerWithData : AFJSONResponseSerializer
@end
// MSJSONResponseSerializerWithData.m
#import "MSJSONResponseSerializerWithData.h"
@implementation MSJSONResponseSerializerWithData
- (id)responseObjectForResponse:(NSURLResponse *)response
data:(NSData *)data
error:(NSError *__autoreleasing *)error
{
if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
if (*error != nil) {
NSMutableDictionary *userInfo = [(*error).userInfo mutableCopy];
userInfo[JSONResponseSerializerWithDataKey] = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSError *newError = [NSError errorWithDomain:(*error).domain code:(*error).code userInfo:userInfo];
(*error) = newError;
}
return (nil);
}
return ([super responseObjectForResponse:response data:data error:error]);
}
@end
以下是我在故障区块中如何使用它的示例。
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"%@",[error.userInfo objectForKey:@"JSONResponseSerializerWithDataKey"]);
}];
答案 1 :(得分:0)
您需要使用AFCompoundSerializer
告诉AFNetworking框架如何处理它可能收到的所有可能响应。默认情况下,它只会尝试映射JSON。复合序列化程序将通过序列化程序,直到找到不会引发错误的序列化程序。
您想使用:
+ (instancetype)compoundSerializerWithResponseSerializers:(NSArray *)responseSerializers
在AFCompoundResponseSerializer
上(AFURLResponseSerialization.h
)。
您需要传递一组可以处理响应的序列化程序。数组中的一个序列化程序应该是AFHTTPResponseSerializer
的实例来处理您的错误响应。
答案 2 :(得分:0)
如果您在项目中包含我的类别,它就像以下一样简单:
[mySessionManager POST:@"some-api" parameters:params success:^(NSURLSessionDataTask *task, NSDictionary *responseObject) {
...
} failure:^(NSURLSessionDataTask *task, NSError *error) {
id responseObject = error.userInfo[kErrorResponseObjectKey];
... do something with the response ...
}];
这是我的类别的代码。它调用AFURLSessionManager将填充程序注入完成处理程序。垫片将响应放入NSError的userInfo。