【コラム】
前回はRSSフィードの一覧を読み込み、ダウンロードを行うところまで解説した。今回は、複数のフィードを並行してダウンロードするためのテクニックについて解説しよう。
前回まででとりあえず、フィードをダウンロードできる。だが、このままではいささか使いづらい。RSSリーダでは、複数のフィードを一度にダウンロードすることが求められる。しかし、数十個のNSURLConnectionを一気に作成したら、帯域を食いつぶしてしまうだろう。同時に行うダウンロード数は、制限できるのが望ましい。1つのダウンロードが終わってから、次のダウンロードを行うようにするのだ。
Cocoaには、このような制御を行う仕組みがある。NSOperationとNSOperationQueueだ。NSOperationは、同時並行に行われる、それぞれの処理を表す。複数のNSOperationの処理を制御するのが、NSOperationQueueだ。いくつかの処理を並行して行い、1つの処理が終わったら、待機中の次の処理を行うようにする。これを使って、フィードのダウンロードを行ってみよう。
まず、ダウンロードを行うための、NSOperationのサブクラスを作る。これを、DownloadOperationという名前にしよう。DownloadOperationは、初期化時にNSURLRequestを指定するようにする。そして、ダウンロードしたデータを取り出すための、プロパティを持つ。
List 4.
@interface DownloadOperation : NSOperation
{
NSURLRequest* _request;
NSURLConnection* _connection;
NSMutableData* _data;
BOOL _isExecuting, _isFinished;
}
// プロパティ
@property (readonly) NSData* data;
// 初期化
- (id)initWithRequest:(NSURLRequest*)request;
@end
_isExecutingや_isFinishedは、処理実行のフラグになる。これらの使い方については、後述する。
このクラスでは、いくつかのNSOperationのメソッドを上書きするのだが、重要なのはstartメソッドだ。このメソッドの中で、処理を開始する。行うのはもちろん、ダウンロードだ。NSURLConnectionを作成して、ダウンロードを開始する。
List 5.
- (void)start
{
// ダウンロードを開始する
if (![self isCancelled]) {
// フラグを設定する
[self setValue:[NSNumber numberWithBool:YES] forKey:@"isExecuting"];
// コネクションを作成する
[NSURLConnection connectionWithRequest:_request delegate:self];
}
}
あとは、NSURLConnectionのデリゲートメソッドの中で、適切な処理を行ってやればいい。
これを使って、フィードをダウンロードしてみよう。まず、NSOperationQueueクラスのインスタンスを作成する。そして、DownloadOperationのインスタンスを作成し、次々とNSOperationQueueに追加してやればいい。そうすれば、適切に同時並行で処理されていくはずだ。
List 6.
// NSOperationQueueを作成する
_queue = [[NSOperationQueue alloc] init];
// フィードをダウンロードする
for (NSString* feed in feeds) {
// URLを指定する
NSURLRequest* request;
request = [NSURLRequest requestWithURL:[NSURL URLWithString:feed]];
// DownloadOperationを作成する
DownloadOperation* operation;
operation = [[DownloadOperation alloc] initWithRequest:request];
[operation autorelease];
// キー値監視を登録する
[operation addObserver:self forKeyPath:@"isFinished"
options:NSKeyValueObservingOptionNew context:nil];
// DownloadOperationを追加する
[_queue addOperation:operation];
}
これで、フィードのダウンロードが開始される。では、ダウンロードが終了した事は、どうやって受け取ればいいのだろうか? これには、キー値コーディングおよびキー値監視が使える。
キー値コーディングとキー値監視は、もともとはCocoaバインディングを実現するために導入された仕組みだ。iPhoneではCocoaバインディングは使えないが、これらの仕組みは使えるようになっている。これにより、NSNotificationとはまた別の種類の通知を行えるようになっている。
DownloadOperationをキー値コーディングに対応させるために、インスタンス変数として_isExecutingと_isFinishedを用意している。それぞれ、ダウンロード処理が実行中かどうか、完了したかどうかを表すものである。
List 5.でダウンロードを行うときに、setValue:forKey:メソッドを使ってフラグを設定した。あれが、キー値コーディングによる設定である。同様に、ダウンロードが終了したときも、isExecutingおよびisFinishedのフラグを設定することになる。このメソッドを使った値の設定を行うと、キー値監視を行っているオブジェクトに通知が飛ぶ。
通知を受け取る側は、キー値監視を行う。これには、List 6.で行っているように、addObserver:forKeyPath:options:context:を使う。通知を受け取ると、observeValueForKeyPath:ofObject:change:context:が呼び出される。確認のために、このメソッドでダウンドードしたデータの大きさを表示させてみよう。
List 7.
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object
change:(NSDictionary*)change context:(void*)context
{
// データの長さを取得する
unsigned int length;
length = [((DownloadOperation*)object).data length];
NSLog(@"data length %d", length);
// キー値監視を解除する
[object removeObserver:self forKeyPath:keyPath];
}
これで、複数のフィードをスマートにダウンロードできる。次回は、ダウンロードしたデータの処理について説明しよう。
ここまでのソースコード: RSS-1.zip
| Skype for Linux 4.2登場 [20:56 5/22] |
| 資生堂、D-アミノ酸の新たな美肌効果を発見 - 化粧品に応用 [19:02 5/22] |
| Cypress、「PSoC 1」用IDE「PSoC Designer」の新バージョンを発表 [16:16 5/22] |
| SCREEN、プリント基板向け直接描画装置の高精細モデルを発表 [16:08 5/22] |
| 東北大、顔料からの有限長カーボンナノチューブ分子の合成に成功 [15:52 5/22] |
|
【インタビュー】神山健治監督が振り返る『009 RE:CYBORG』 - Blu-ray/DVDが5月22日発売 [00:30 5/23] ホビー |
|
弐瓶勉の正道ロボットSF「シドニアの騎士」がアニメ化 [00:00 5/23] ホビー |
|
クウガからウィザードまで! 一番くじ"仮面ライダー平成オールスター編"登場 [00:00 5/23] ホビー |
|
ブラッド・ピット、手術前にアンジェリーナ・ジョリーへ愛の手紙を読み上げて涙する [00:00 5/23] エンタメ |
|
Wii Uのバーチャルコンソールで『ロックマンX』の配信がスタート! [00:00 5/23] ホビー |