如何在NSURLResponse中设置statusCode

时间:2010-12-08 02:47:50

标签: iphone objective-c nsurlprotocol

我重写NSURLProtocol并需要返回具有特定statusCode的HTTP响应。 NSHTTPURLResponse没有statusCode setter,所以我尝试用以下方法覆盖它:

@interface MyHTTPURLResponse : NSHTTPURLResponse {} 

@implementation MyHTTPURLResponse

    - (NSInteger)statusCode {
        return 200; //stub code
    }
@end

NSURLProtocol的重写startLoading方法如下所示:

-(void)startLoading
{   
   NSString *url = [[[self request] URL] absoluteString];
   if([url isEqualToString:SPECIFIC_URL]){
       MyURLResponse *response = [[MyURLResponse alloc] initWithURL:[NSURL URLWithString:@"http://fakeUrl"]
       MIMEType:@"text/plain"
       expectedContentLength:0  textEncodingName:nil];

       [[self client] URLProtocol:self     
            didReceiveResponse:response 
            cacheStoragePolicy:NSURLCacheStorageNotAllowed];

       [[self client] URLProtocol:self didLoadData:[@"Fake response string"
            dataUsingEncoding:NSASCIIStringEncoding]];

       [[self client] URLProtocolDidFinishLoading:self];                

       [response release];

    }
    else{   
        [NSURLConnection connectionWithRequest:[self request] delegate:self];   
    }
}

但是这种方法不起作用,在NSURLProtocol中创建的响应总是在网页上使用statusCode = 0。同时,NSURLConnection从网络返回的响应具有正常的预期statusCodes。

任何人都可以请教如何为创建的NSURLResponse显式设置statusCode吗?感谢名单。

3 个答案:

答案 0 :(得分:9)

这是一个更好的解决方案。

在iOS 5.0及更高版本中,您不必再使用私有API或重载NSHTTPURLResponse做任何疯狂的事情。

要使用您自己的状态代码和标题创建NSHTTPUTLResponse,您现在只需使用:

initWithURL:statusCode:HTTPVersion:headerFields:

生成的文档中未记录,但 实际存在于NSURLResponse.h头文件中,并且还标记为OS X 10.7和iOS 5.0上提供的公共API。< / p>

另请注意,如果您使用NSURLProtocol技巧从XMLHTTPRequest拨打UIWebView来电,那么您需要正确设置Access-Control-Allow-Origin标头。否则,XMLHTTPRequest安全性会启动,即使您的NSURLProtocol将收到并处理请求,您也无法发回回复。

答案 1 :(得分:4)

您只能从URLResponse获取状态代码。无需明确设置: -

    NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&requestError];  

    NSString *responseString = [[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding] autorelease];
    NSLog(@"ResponseString:%@",responseString);

    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
    int statusCode = [httpResponse statusCode];
    NSLog(@"%d",statusCode);

答案 2 :(得分:4)

我使用以下代码实现了自定义init方法:

    NSInteger statusCode = 200;
    id headerFields = nil;
    double requestTime = 1;

    SEL selector = NSSelectorFromString(@"initWithURL:statusCode:headerFields:requestTime:");
    NSMethodSignature *signature = [self methodSignatureForSelector:selector];

    NSInvocation *inv = [NSInvocation invocationWithMethodSignature:signature];
    [inv setTarget:self];
    [inv setSelector:selector];
    [inv setArgument:&URL atIndex:2];
    [inv setArgument:&statusCode atIndex:3];
    [inv setArgument:&headerFields atIndex:4];
    [inv setArgument:&requestTime atIndex:5];

    [inv invoke];