Как установить statusCode в NSURLResponse - PullRequest
10 голосов
/ 08 декабря 2010

Я переопределяю NSURLProtocol и мне нужно вернуть HTTP-ответ с определенным statusCode. NSHTTPURLResponse не имеет установщика statusCode, поэтому я попытался переопределить его с помощью:

@interface MyHTTPURLResponse : NSHTTPURLResponse {} 

@implementation MyHTTPURLResponse

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

Переопределенный метод startLoading NSURLProtocol выглядит следующим образом:

-(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, имеют нормальные ожидаемые коды состояния.

Может кто-нибудь помочь с идеями, как явно установить statusCode для созданного NSURLResponse? Thanx.

Ответы [ 3 ]

9 голосов
/ 02 марта 2012

Вот лучшее решение.

В iOS 5.0 и более поздних версиях вам больше не нужно ничего делать с частными API или перегрузкой NSHTTPURLResponse.

Чтобы создать NSHTTPUTLResponse с вашим собственным кодом состояния и заголовками теперь вы можете просто использовать:

initWithURL:statusCode:HTTPVersion:headerFields:

, который не задокументирован в сгенерированной документации, но действительно присутствует в заголовочном файле NSURLResponse.h итакже помечен как общедоступный API, доступный в OS X 10.7 и iOS 5.0.

Также обратите внимание, что если вы используете трюк NSURLProtocol для совершения XMLHTTPRequest вызовов с UIWebView, то вы будетенеобходимо правильно установить заголовок Access-Control-Allow-Origin.В противном случае включится защита XMLHTTPRequest, и даже если ваш NSURLProtocol получит и обработает запрос, вы не сможете отправить ответ обратно.

4 голосов
/ 08 августа 2011

Я реализовал пользовательский метод 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];
4 голосов
/ 08 декабря 2010

U получить код состояния только из 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);
...