Hatena::ブログ(Diary)

cooldaemonの備忘録 RSSフィード

2009-08-19

手軽に別スレッドで HTTP 通信を行う Objective-C のライブラリを作りました

iPhone アプリ開発の手始めに、NSURLConnection と NSOperation を組み合わせた Simple Http Client というモジュールを作りました。

使い方は、付属のテストコードを読んで頂けると、簡単に理解できると思います。

とても行数が少ないので、作る価値があったのか謎ですが(w;

cooldaemon’s SimpleHttpClient at master - GitHub

初めての Objective-C なので、突っ込み&添削は大歓迎です。

機能追加しました。詳細は、SimpleHttpClient に JSON と XML のフィルタを追加しました をご参照ください。

HTML フィルタも追加しました。HTML に対して XPath が使えます。

NSOperationQueue を外部から与えられるようにしました。当たり前の事ですが、スレッドを管理するキューは、一つの iPhone アプリに対して、一つで十分だと思います。

SimpleHttpClient を用いた iPhone アプリのサンプルプロジェクトを公開しました。

テストコードの解説

初期化
SimpleHttpClient *client = [[SimpleHttpClient alloc] initWithDelegate:self];

まずは、SimpleHttpClient のオブジェクトを作ります。

引数として delegate を渡していますが、リクエスト毎に delegate を変更する事も出来ます。

GET リクエスト

例えば、下記のような GET リクエストを発行したいとします。

http://foo.bar/search?q=iphone&q=osx&lr=lang_en

その場合は、下記のような辞書オブジェクトを作成し・・・

NSMutableDictionary *params = [NSMutableDictionary
    dictionaryWithObject:[NSArray arrayWithObjects:@"iphone", @"osx", nil]
                  forKey:@"q"
];
[params setObject:@"lang_en" forKey:@"lr"];

辞書オブジェクトを JSON 風に表現すると下記のような感じです。

{
  q  : ['iphone', 'osx'],
  lr : 'lang_en'
}

Value は、NSArray と NSString 以外は無視されるので気をつけて下さい。

これを、先ほど作成した SimpleHttpClient のオブジェクトに登録します。

[client
           get:@"http://foo.bar/search"
    parameters:params
       context:@"iphone"
];

context は、後ほど説明します。

この時点で、別スレッド上で GET リクエストが実行されます。実際には、負荷が高ければキューに積まれ、負荷が下がるのを待ってから実行されるのですが、この辺りは、NSOperation と NSOperationQueue 任せです。

POST リクエスト

上記の 'get' を 'post' に変更します。

[client
          post:@"http://foo.bar/search"
    parameters:params
       context:@"iphone"
];
データの受信

NSURLConnection でよく使われるメソッドだけラップしてあります。

気をつけるべき点は、別スレッドで同時に動いているので、一つの delegate にメッセージが集中する事です。(リクエスト時、個別に delegate を指定した場合は別です。)

その為、リクエスト時に指定した context を利用して処理を分岐させます。

例えば、didReceiveResponse を受け取る場合は、下記のようにします。

- (void)simpleHttpClientOperation:(SimpleHttpClientOperation *)operation
didReceiveResponse:(NSHTTPURLResponse *)response
{
    [_response setObject:response forKey:operation.context];
} 

operation.context には、リクエストを登録する際に引数として渡した context が入っています。

これを利用して、処理を分岐させて下さい。

その他

GET、POST 共に priority を指定できます。緊急度の高いリクエストを優先的に行ったり、暇な時に行えば良いリクエストを後回しにしたりできます。

詳細は、NSOperation のマニュアルをご参照ください。

もし利用者がいらっしゃるようでしたら、もう少し、マシな解説を書きます。

queen9999queen9999 2010/01/19 15:05 はじめまして、x-codeを使用しはじめたばかりなので、よくわかっていないのですが
このSimpleHttpClientを自分のプロジェクトに追加する場合どのようにしたらよろしいのでしょうか
git からソースファイルのダウンロードをすませて、/test/make はできたようです。

恐れ入りますがよろしくお願いいたします。

cooldaemoncooldaemon 2010/01/20 13:32 ご利用ありがとうございます。

KissXML を内部で利用している都合上、下記が参考になると思います。
http://iphone.longearth.net/2009/08/12/%E3%80%90iphone%E3%80%91kissxml%E3%81%A7%E5%BF%AB%E9%81%A9%E3%83%91%E3%83%BC%E3%82%B9%E7%94%9F%E6%B4%BB/

詳しい利用準備の方法は、後日改めてブログに記載しようと思います。

queen9999queen9999 2010/01/20 16:34 早速のお返事ありがとうございました。
iPhoneのアプリに利用できないかなと思って試行錯誤していたのですが
NSXMLDocumentationですかね、これがiPhoneには使用できないようでした。
お騒がせいたしました。 コードの勉強に利用させていただきますよろしくお願いします。

cooldaemoncooldaemon 2010/01/20 19:24 以前、10.5 で開発した際には、シュミレータと iPhone 実機上で動作を確認しております。

その後、10.6 に入れ替えた際、NSOperation 周りを修正したのですが
そちらは、シュミレータでも、iPhone の実機上でも動作確認しておりません。

時間がある時に、こちらでも試してみます。

cooldaemoncooldaemon 2010/01/20 23:53 先ほど、シュミレータにて確認したところ、確かに一箇所 NSXMLDocumentation を使用している箇所がありました。
修正させて頂きましたので、最新版でお試し頂ければ幸いです。

後ほど、プロジェクトディレクトリを公開させて頂きます。

cooldaemoncooldaemon 2010/01/22 14:13 iPhone アプリのサンプルプロジェクトを github に置きました。
http://github.com/cooldaemon/TestSimpleHttpClient

a-j1b1k1a-j1b1k1 2012/02/18 00:57 cooldaemon さん
面白そうなコードですね。

私、今、Rest通信をするアプリを開発中です。
最後のコメントから2年がすぎていますが、質問があるときにこの件について、コメントをさせていただいてもよろしいでしょうか?

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。

トラックバック - http://d.hatena.ne.jp/cooldaemon/20090819/1250613707