2012/07/31更新

[XCODE] NSURLResponseからステータスコードやHTTPヘッダを取り出す方法

このエントリーをはてなブックマークに追加            

こんにちは、@yoheiMuneです。
今日はマニアックなネタですが、NSURLConnectionを用いたサーバー通信において、 サーバーレスポンスからステータスコードやHTTPヘッダを取得する方法をブログに書きます。

画像



NSURLConnectionを用いた通信

iOSには、いくつかのサーバーとの通信方法がありますが、NSURLConnectionを用いた場合には、 以下のようなソースコードで、非同期(NonBlocking-IO)でサーバーと通信を行うことが出来ます。
(サーバーと通信を行うクラスの例)
/* ヘッダファイル情報 */
#import 

@interface SampleLoader : NSObject {

  // レスポンス情報を格納する変数
  NSMutableData *receivedData;


  //   通信終了後に呼び出すコールバック関数情報を格納する変数
  id  client;
  SEL method;
}


-(void)loadWithURL:(NSString *)urlStr target:(id)t method:(SEL)m;
@end

/* 実装クラス情報 */
@implementation SampleLoader 

-(void)loadWithURL:(NSString *)urlStr target:(id)t method:(SEL)m {

  target = t;
  method = m

  // 通信を開始する
  NSURL *url = [NSURL urlWithString:urlStr];
  NSURLRequest *request = [NSURLRequest requestWithURL:url];
  NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
  if (conn == nil)
    NSLog(@"request failed.");
}

#pragma mark - NSURLConnectionDelegate
// サーバーからの戻りが始まった際に呼び出されるメソッド。
- (void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *)response {
    receivedData = [[NSMutableData alloc] init];
}
// サーバーからデータを受信するたびに呼び出されるメソッド。
- (void) connection:(NSURLConnection *) connection didReceiveData:(NSData *)data {
    [receivedData appendData:data];
}

// 通信が終了したら呼び出されるメソッド。
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
  NSString *retValue = [[NSString alloc] initWithBytes:data.bytes length:data.length encoding:NSUTF8StringEncoding];

  if (client && callbackMethod)
    [clientperformSelector:callbackMethod withObject:nil withObject:retValue];

}
// 通信が失敗したら呼び出されるメソッド。
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    
    rsslog(@"request failed. code=%d, %@ - %@",
           error.code,
           [error localizedDescription],
           [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]); 
    
    if (client && callbackMethod)
        [clientperformSelector:callbackMethod withObject:error withObject:nil];
}
@end

上記の問題点の一つは、サーバーからのレスポンスのステータスが200以外でも、 「connectionDidFinishLoading」が呼び出される点です。
上記のソースコードでは、成功したのか失敗したのか(401とか300とか)が分かりません。



レスポンスのステータスコードを取得する方法

そのため、ステータスコードの取得が必要となります。
「connection:didReceiveResponse:」メソッドを以下のように実装することで、HTTPステータスコードを取得できます。
- (void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *)response {
    receivedData = [[NSMutableDataalloc] init];
    statusCode = ((NSHTTPURLResponse *)response).statusCode;
}

ポイントは、NSURLResponseをNSHTTPURLResponseにダウンキャストする点です。
HTTPプロトコルの通信であれば、NSHTTPURLResponseにダウンキャストできます。

また他にも、レスポンスのHTTPヘッダは以下のように取得します。
NSDictionary *headerInfo = ((NSHTTPURLResponse *)response).allHeaderFields;
headerInfoから、キーを指定してヘッダ情報を取得します。



関連情報

iOSでのサーバーとの通信関連について、他にも記事がありますので、参考になれば幸いです。
- [XCODE] iPhoneアプリからHTTPリクエストを送信して、データを受信する方法
- [XCODE] iPhoneアプリからHTTP送信する際に、POST送信、ヘッダ付与、クッキー付与を行う方法
- [Web] HTTPリクエストの中身を学んでみた。GETやPOSTの違いなど



最後に

少しずつサーバーとの通信処理が実装できるようになってきてウキウキ気分です。
もう少ししたらもっと低レベルAPIを用いて、ソケットとか理解しながら実装できるようになりたいなぁと思う今日この頃です。

最後までお読み頂きましてありがとうございました。






こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。