AFNetworking 2.0 // 如何读取响应头

12

我正在使用新版本的AFNetworking,但是我无法找到如何读取响应头的方法。我使用AFHTTPSessionManager执行我的查询,一切正常,但是我无法找到响应头字段。

这是我的步骤:

self.sessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:BASE_URL]];
[self.sessionManager GET:urlId parameters:nil
    success:^(NSURLSessionDataTask *task, id responseObject) {
        if ([self.delegate respondsToSelector:@selector(userIsLoadedWithInfos:)]) {
            [self.delegate userIsLoadedWithInfos: responseObject];
        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        if ([self.delegate respondsToSelector:@selector(userLoadingFailed)]) {
            [self.delegate userLoadingFailed];
        }
    }
];

我尝试读取任务的响应属性,但它返回一个NSURLResponse,其中不包括标头。

有人知道如何在2.0版本中读取响应标头吗?

5个回答

16

比Viruss mcs的代码稍微更健壮一些:

if ([task.response isKindOfClass:[NSHTTPURLResponse class]]) {
    NSHTTPURLResponse *r = (NSHTTPURLResponse *)task.response;
    NSLog(@"%@" ,[r allHeaderFields]);
}

返回

{
    Connection = "Keep-Alive";
    "Content-Length" = 12771;
    "Content-Type" = "application/json";
    Date = "Fri, 06 Dec 2013 10:40:48 GMT";
    "Keep-Alive" = "timeout=5";
    "Proxy-Connection" = "Keep-Alive";
    Server = "gunicorn/18.0";
}

同样地,你可以使用[response respondsToSelector:@selector(allHeaderFields)]确保转换正确,但在进行转换之前,你也应该调用该方法。

if ([task.response respondsToSelector:@selector(allHeaderFields)]) {
    NSHTTPURLResponse *r = (NSHTTPURLResponse *)task.response;
    NSLog(@"%@" ,[r allHeaderFields]);
}

或者干脆不转换:

if ([task.response respondsToSelector:@selector(allHeaderFields)]) {
    NSLog(@"%@" ,[task.response performSelector:@selector(allHeaderFields)]);
}

13

您是否尝试过从返回的NSURLResponse中获取标头?

您可以尝试使用NSURLResponse对象进行类似操作,

NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
if ([httpResponse respondsToSelector:@selector(allHeaderFields)]) {
    NSDictionary *dictionary = [httpResponse allHeaderFields];
    NSLog([dictionary description]);
}

希望这将对您有所帮助!


我已经尝试过了,但似乎NSURLResponse没有包含allHeaderFields方法。只有NSHTTPURLResponse类才包含它。 - M to the K
@MtotheK:请检查更新后的答案,将您的响应转换为NSHTTPURLResponse。 - Toseef Khilji
2
@Virussmca:请不要把类型转换称为类型转换。这样会产生歧义。 - vikingosegundo
1
我尝试了完全相同的事情,它起作用了,所以你的答案是正确的,谢谢你的帮助! - M to the K
2
你的类型转换和选择器检查实际上是顺序错误的:如果它响应allHeaderFields,那么你知道可以安全地将其转换为具有此方法的类。 - vikingosegundo
显示剩余3条评论

4

有趣的是,上面的回应表明参数 id responseObject 返回一个 NSURLResponse。而我在后端运行的是JAX-RS服务器,我得到的响应却不同。当我对我的服务器执行一个 curl 命令时,我的响应是这样的:

$ curl -v "http://10.0.1.8:3000/items"
* About to connect() to 10.0.1.8 port 3000 (#0)
*   Trying 10.0.1.8...
* Adding handle: conn: 0x7f9f51804000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7f9f51804000) send_pipe: 1, recv_pipe: 0
* Connected to 10.0.1.8 (10.0.1.8) port 3000 (#0)
> GET /items HTTP/1.1
> User-Agent: curl/7.30.0
> Host: 10.0.1.8:3000
> Accept: */*
>
< HTTP/1.1 200 OK
< ETag: af0057e2-1c6d-4a47-b81a-a754238b60fd
< Content-Type: application/json
< Content-Length: 255
< Connection: keep-alive
<
* Connection #0 to host 10.0.1.8 left intact
[{"name":"Item1","uid":"F465AAD2-AA39-4C33-A57A-F0543C25C476"},
 {"name":"Item2","uid":"6505A82E-A473-4A7D-BC4B-BCBEFFFE8E9C"}]

我的responseObject是服务器响应主体中的项目数组,而不是NSURLResponse。以下是我如何检索标题:

void (^handleSuccess)(NSURLSessionDataTask *, id) = ^(NSURLSessionDataTask *task, id responseObject) {
    // handle response headers
    NSHTTPURLResponse *response = ((NSHTTPURLResponse *)[task response]);
    NSDictionary *headers = [response allHeaderFields];

    // handle response body
    NSArray *responseItems = responseObject;
    for (NSDictionary *item in responseItems) {
        [self.activeDataController createObject:item];
    }
};

为什么被接受的答案是错误的完美解释。 - dmzza

3

我对AFHTTPRequestOperationManager进行了子类化,并使用了以下代码:

- (AFHTTPRequestOperation *)POST:(NSString *)URLString
                      parameters:(NSDictionary *)parameters
                         success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
                         failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;

对于我的大多数Web服务请求,我使用的是一种方法。使用该方法时,响应头将成为操作对象的一部分。类似于以下内容:

[self POST:url parameters:newParams success:^(AFHTTPRequestOperation *operation, id responseObject) {
    // Response headers will be a dictionary
    NSDictionary *headers = operation.response.allHeaderFields;
...

0

对于Swift 2.0:

if let response = operation.response {
    print(response.allHeaderFields)
}

1
虽然这段代码片段可能解决了问题,但是在代码之外加入解释真的有助于提高您的帖子质量。请记住,您正在为未来的读者回答问题,而这些人可能不知道您的代码建议原因。请尽量不要在代码中添加解释性注释,这会降低代码和解释的可读性! - Kyll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接