★ 外部の関数を取り入れる場合のいろいろ
json-framework
SimpleHttpClient
-----------------------------------------------------------------------------------
buildの設定のところで
Link Binary With Libraries
libxml2.dylib 追加する
Other Linker Flags
-xml2 を追加する
Header Search Paths
/usr/include/libxml2 を追加する
-----------------------------------------------------------------------------------
・SimpleHttpClient
https://github.com/cooldaemon/SimpleHttpClient
http://d.hatena.ne.jp/cooldaemon/20100122/1264137498#
↑大変ありがとうございます。
・DDXML+HTML
https://gist.github.com/185012
——————————————————————————————————
・json-framework
http://code.google.com/p/json-framework/
単に"Classes"というfolderごとコピーする方法が簡単
使いたいところで
・ #import "JSON.h"
-----------------------------------------------------------------------------------
・SimpleHttpClientの説明
https://github.com/cooldaemon/SimpleHttpClient
JSON と XML のフィルタを追加
HTML フィルタも追加
(HTML に対して XPath が使えます)
NSOperationQueue を外部から与えられるようにしました。
スレッドを管理するキューは、
一つの 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 のマニュアルをご参照ください。
-----------------------------------------------------------------------------------
iPhone アプリのサンプルプロジェクト
http://github.com/cooldaemon/TestSimpleHttpClient
-----------------------------------------------------------------------------------
・SimpleHttpClient に JSON と XML のフィルタ
WSSE に対応した際と同じくドメイン毎にフィルタを設定できるので、
reader.livedoor.com から取得したデータは JSON フィルタを通す、
b.hatena.ne.jp から取得したデータは XML フィルタを通す
・・・という使い方が可能です。
具体的には、下記のように設定を行ないます。
SimpleHttpClient *client = [[[SimpleHttpClient alloc] initWithDelegate:self] autorelease];
[client
setFilter :SimpleHttpClientFilterJSON
forHost :@"reader.livedoor.com"
];
[client
setFilter :SimpleHttpClientFilterXML
forHost :@"b.hatena.ne.jp"
];
もし、http://reader.livedoor.com/api/subs に対してリクエストを送ったのであれば、
フィルタ済みのデータを受け取るには下記のようにします。
- (void)simpleHttpClientOperationDidFinishLoading
: (SimpleHttpClientOperation *)operation
filteredData : (id)data
{
_subs = (NSArray *)[data retain];
}
http://reader.livedoor.com/api/subs は、Array 型の JSON を返すので NSArray * にキャストします。
data は autorelease 済みであり、
simpleHttpClientOperationDidFinishLoading:filteredData:
メッセージは、サブスレッドの中で呼ばれるので、retain しておかないと、
サブスレッド終了時に NSAutoreleasePool に release されてしまいます。
-----------------------------------------------------------------------------------
・SimpleHttpClient に KissXML+HTML を組み込んだHTML フィルタ
下記のように、SimpleHttpClient のオブジェクトを作成し・・・
SimpleHttpClient *client = [[SimpleHttpClient alloc] initWithDelegate:self];
HTML 用のフィルタを設定し・・・
[client
setFilter:SimpleHttpClientFilterHTML
forHost:@"d.hatena.ne.jp"
];
リクエストを送ると・・・
[client
get :@"http://d.hatena.ne.jp/cooldaemon/20090911/1252637257"
parameters :nil
context :nil
];
DDXMLDocument のオブジェクトが受け取れます。
- (void)simpleHttpClientOperationDidFinishLoading:(SimpleHttpClientOperation *)operation
filteredData:(id)data
{
[_html release];
_html = (DDXMLDocument *)[data retain];
}
XPath を使うには、下記のようにします。
NSError *error = nil;
NSArray *body = [_html
nodesForXPath:@"id(\"days\")//div[@class=\"body\"]//h3/following-sibling::*|id(\"days\")//div[@class=\"body\" and not(.//h3)]"
error:&error
];
NSLog("%@", [body componentsJoinedByString:@""]);
詳しくは、test/TestHatenaDiaryHTML.mを参照
0 件のコメント:
コメントを投稿