Level 6 簡易RSSリーダー

-contents-

1. RSSリーダーとは

Webサイトを巡回してRSS形式の更新情報を受信し、 リンク一覧の形で表示するアプリケーションソフトである。 指定したサイトのRSS情報を一定時間ごとに自動的にダウンロードし、 更新があると記事へのリンクを表示してユーザに知らせるのが一般的である。

今回作成する簡易RSSリーダーは、あらかじめRSSを追加して一覧化し、 Parseボタンを押すと選択したRSS情報をダウンロードし、画面に表示するものとする。

2. アプリケーションの概要

作成、実行環境

今回作成するアプリケーションの主なルーチンを以下に示す。

Controller メインウィンドウ、RSSの読み込み、起動及び終了の処理
AddUrl サブウィンドウ、RSSの追加及び削除処理
NSTextViewWithLinks リンク上でマウスカーソルを変化させる。

これらは以下からダウンロードできる。

プロジェクト一式
Controller.m
AddUrl.m
NSTextViewWithLinks.m

各ルーチンでの処理は以下の節で説明する。

3. プログラムの説明

3.1 ウィンドウ

ウィンドウやその他デザイン等はInterface Builderで作成した。

メインウィンドウ

図1. メインウィンドウ


Parseボタンを押すと- (IBAction)getContents:(id)senderメソッドが呼び出され、
TextField中のRSS情報のダウンロードを開始する。
- (IBAction)getContents:(id)sender
{
  // 指定したURL
  // selUrlはComboBoxのインスタンス
  NSURL *url = [NSURL URLWithString: [selUrl stringValue]]; 
  ・・・  
}
サブウィンドウ

図2. RSS追加及び削除ウィンドウ


追加ボタンを押すと、- (IBAction)addURL:(id)senderが呼び出され、TextField中のURLをメインウィンドウのComboBoxに追加する。
また、削除ボタンを押すと - (IBAction)rmURL:(id)sender; が呼ばれ、メインウィンドウのComboBoxの要素をすべて削除する。
- (IBAction)addURL:(id)sender
{
  NSString    *url  = [addUrl stringValue];
  [selUrl setUsesDataSource:NO];
  [selUrl addItemWithObjectValue: url];
}

- (IBAction)rmURL:(id)sender;
{
  [selUrl setUsesDataSource:NO];
  [selUrl removeAllItems];
}

3.2 RSS情報の読み込み、解析

通常、RSSリーダーではXML文書であるRSSを利用する際に、 XMLパーサというソフトウェアを使用する。 XMLはテキストファイルの形で存在するため、そのままアプリケーションで 利用するのは困難である。 しかし、一定の形式が定められているため、汎用的な解釈プログラムである XMLパーサによって変換したデータを使うほうが効率が良い。

今回はObject-Cに用意されているパーサとして、NSXMLParserを使用する。 しかし、NSXMLParserはツリー構造にパースしてくれるわけではなく、 XML文書の最初から読み下っていき、「どんなタグが始まった」 「どんな値が入っていた」という処理を逐一拾っていくという方式を とらなければならない。 そこで、NSXMLParserのデリゲートをControllerのインスタンスにセットする。
// 指定したURLからデータを読み込んで、
// XMLパーサオブジェクトを返す。
NSXMLParser *parser = [ [ NSXMLParser alloc ] initWithContentsOfURL:url];

// デリゲートをセット
[parser setDelegate:self];
urlはメインウィンドウでTextFieldに入力されていたURLである。 デリゲートをセットすることで、パース中に以下のメソッドが間接的に 呼び出されるため、RSSの解析がしやすくなる。
// ドキュメントのパースの開始
- (void)parserDidStartDocument:(NSXMLParser *)parser;

// ドキュメントのパースの完了
- (void)parserDidEndDocument:(NSXMLParser *)parser;

// タグの開始
- (void)parser:(NSXMLParser *)parser 
    didStartElement:(NSString *)elementName 
    namespaceURI:(NSString *)namespaceURI 
    qualifiedName:(NSString *)qName 
    attributes:(NSDictionary *)attributeDict
  
// タグの中身
- (void)parser:(NSXMLParser *)parser 
    foundCharacters:(NSString *)string;

// タグの終了
- (void)parser:(NSXMLParser *)parser 
    didEndElement:(NSString *)elementName 
    namespaceURI:(NSString *)namespaceURI 
    qualifiedName:(NSString *)qName;
各メソッドでタグを認識したり、その時の値を読み込むなどの処理を行っている。

3.3 RSS情報の出力

RSSのパースに成功すると、メインウィンドウのTextViewへの出力処理を開始する。

今回は「title」「description」「link」項目を出力するが、 「link」に関しては『クリックするとブラウザで開く』という動作を行うようにする。
// NSDictionary:キーと値のペアを格納する連想配列クラス
// contents:RSS情報から取り出した「link」の値

NSDictionary *attrs = [NSDictionary dictionaryWithObject:contents forKey:NSLinkAttributeName];

// temp:NSAttributedStringクラス
// 属性(色やフォントなど)の情報をもつ文字列クラス

temp = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n",contents] attributes:attrs];
まず「contentsはリンクである」という情報をattrsに格納し、 それからリンクの属性をcontentsに付加してtempに返す。 こうすることにより、クリックするとデフォルトブラウザが起動する処理が行われるようになる。

HTMLタグで例えると
<a href="http://www.ie.u-ryukyu.ac.jp">情報工学科</a>
の場合、「<a herf="・・"></a>」の部分がattrs、「情報工学科」の部分がcontentsになる。

また、リンク上でマウスカーソルが変化するような処理も行っている。これは
(http://developer.apple.com/samplecode/TextLinks/TextLinks.html)
からNSTextViewWithLinks. {m,h}、fingerCursor.tiff をダウンロードし、 プロジェクトに追加する事により実現した。

fingerCursorは以下のような画像である。(拡大表示)
指

3.4 設定の保存・読み込み

アプリケーションの起動時と終了時に、RSS の追加及び削除に関する設定を保存する処理を行う。
// アプリケーション終了処理 
// 環境設定を保存 
- (void)windowWillClose:(NSNotification *)aNotification 
{ 
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
  NSArray *temp = [[NSArray alloc] initWithArray:[selUrl objectValues] ];
  [selUrl setUsesDataSource:NO]; 
  [defaults setObject:temp forKey:@"listUrl"]; 
  [defaults synchronize]; 
}
まず NSUserDefaults という、初期設定を操作するクラスのインスタンス化を行う。 そして「listUrl」というキーで RSS の情報が格納されている配列をdefaultsにセットする。 その後の synchronize にて初期設定ファイルに保存される。 ここで、初期設定ファイルはプロジェクト中の Info.plist で指定した名前で"~/Library/Preferences/*.plist”に保存される。

// アプリケーションの起動処理 
// 環境設定の読み込み 
- (void) applicationDidFinishLaunching: 
(NSNotification *)aNotification 
{ 
[spin setDisplayedWhenStopped:NO]; 
NSUserDefaults *defaults = 
[ NSUserDefaults standardUserDefaults ]; 
id sel = [defaults objectForKey:@"listUrl"]; 
// selUrl:メインウィンドウの ComboBox のインスタンス 
[selUrl setUsesDataSource:NO]; 
[selUrl addItemsWithObjectValues:sel]; 
} 
初期設定から、「listUrl」というキーに格納されている値を sel に返し、
メインウィンドウの ComboBox に追加するという流れである。

4. 実行結果

実行画面

5. 今後の課題

RSS には異なるバージョンがいくつか存在し、 それはバージョンアップではなく派生したものという少し複雑な状況が発生している。 また、それに対抗しようと新たなフォーマット(Atom や OPML など)も作成されてきており、 今回のような単純に入力された URL から情報をとるという方式では、 いくつかの RSS では情報が読み切れずエラーを起こしたり結果が出力されなかったりする。 今回は簡易 RSS リーダということで異なるバージョンへの対処はしきれなかったが、 さらに上のレベルのアプリケーションを作成するのであればこういった互換性に対しての処理が必要になってくるであろう。

参考文献


もどる   Level 1   Level 3