iphoneアプリ開発日記その5
RSS リーダーを作る
突然 RSS リーダーが作りたくなった。
参考になりそうなページがあったので、とりあえず見てみる。
【コラム】実践! iPhoneアプリ開発 (5) RSSリーダの作り方 (1) - RSSフィードをダウンロードする | 開発・SE | マイナビニュース
【iPhone開発】RSSを読み込む方法 | STUDIO BEATNIX
おお、動く動く
…がいまいち挙動がわからん。
コード見てもさっぱりさっぱり。
こういうときは、問題を切り分けて個別にやっつけていこう。
RSS リーダーの処理を考えると、こんな感じになるか
それに加えて、「ダウンロード → パース」を並列化している。
なのでその辺も理解する必要がある。
xml パーサーの動きをみる
まずは xml パーサから。
選択肢はこの5つ
名前 | 解析タイプ | 備考 |
---|---|---|
NSXMLParser | SAX | ios標準 |
libxml2 | SAX | ios標準、c言語API |
GDataXML | DOM | google製 |
KissXML | DOM | |
TBXML | DOM |
性能評価はこのへんHow To Choose the Best XML Parser for your iPhone Project
そのうち読みたい
以前 pyhton で sax パーサを作った気がするので、今回も sax で。
標準的な NSXMLParer を使うことにしよう。
最低限以下のメソッドを実装すれば動くようだ
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
ひとまずこれでログを吐きまくると、挙動のイメージがつきそうだ。
さて、ここで何のタグを解析すればいいのか、ということに思い当たる。
RSS の xml ってどういう構成になってるのだろうか。
RSS フィードの構成を調べる
RSS のフィード構成がどうなっているのかを調べてみた。
このへんを参考に⬇
RSSのフォーマット・仕様・構造 - RSS1.0、RSS2.0、Content-Type
RSS(RDF Site Summary)によるサイト情報の要約と公開
大きな要素として、channel と item があって、その中にいろいろ情報が入ってる
入ってる情報の中で、使いそうなものはこのへんか
- title
- link
- description
- pubDate
なお、date に関しては、標準の pubDate を使っていたり、拡張モジュールの dc:date を使っていたりする。
そのため、一応両対応しておこう。
xmlを解析してみる
さて、RSS フィードをばらしてみよう
作ったサンプルコード
XMLParser.h
#import <Foundation/Foundation.h> @interface XMLParser : NSObject<NSXMLParserDelegate>{ NSXMLParser* parser; NSMutableDictionary* feedsDict; BOOL isChannel; BOOL isItem; } - (void)parseRSS: (NSURL*) url; @end
XMLParser.m
#import "XMLParser.h" @implementation XMLParser static NSString* CHANNEL_KEY = @"channel"; static NSString* ITEM_KEY = @"item"; - (void)parseRSS: (NSURL*)url{ parser = [NSXMLParser.new initWithContentsOfURL:url]; parser.delegate = self; [parser parse]; } - (void)parserDidStartDocument:(NSXMLParser *)parser{ feedsDict = NSMutableDictionary.new; isChannel = NO; isItem = NO; } - (void)parserDidEndDocument:(NSXMLParser *)parser{ isChannel = NO; isItem = NO; } - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{ if ([elementName isEqualToString:CHANNEL_KEY]){ NSLog(@"channel %@ start", elementName); isChannel = YES; }else if ([elementName isEqualToString:ITEM_KEY]){ NSLog(@"item %@ start", elementName); isItem = YES; } else{ NSString* log_prefix = @"other"; if(isChannel){ log_prefix = CHANNEL_KEY; }else if (isItem){ log_prefix = ITEM_KEY; } NSLog(@"%@ element: %@ : start", log_prefix, elementName); } } - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{ if ([elementName isEqualToString:CHANNEL_KEY]){ NSLog(@"channel %@ end", elementName); isChannel = NO; }else if ([elementName isEqualToString:ITEM_KEY]){ NSLog(@"item %@ end", elementName); isItem = NO; }else{ NSString* log_prefix = @"other"; if(isChannel){ log_prefix = CHANNEL_KEY; }else if (isItem){ log_prefix = ITEM_KEY; } NSLog(@"%@ element: %@ : end", log_prefix, elementName); } } - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ NSString* trimmedString = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; if (![trimmedString isEqualToString:@""]) { NSLog(@"found: %@", string); } } - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{ NSLog(@"error: %@", parseError); } @end
結果(channel)
2013-06-06 19:52:16.885 CUILesson[82227:303] other element: rdf:RDF : start 2013-06-06 19:52:16.887 CUILesson[82227:303] channel channel start 2013-06-06 19:52:16.887 CUILesson[82227:303] channel element: title : start 2013-06-06 19:52:16.887 CUILesson[82227:303] found: 4Gamer.net 2013-06-06 19:52:16.888 CUILesson[82227:303] found: − 最新記事 2013-06-06 19:52:16.888 CUILesson[82227:303] channel element: title : end 2013-06-06 19:52:16.888 CUILesson[82227:303] channel element: link : start 2013-06-06 19:52:16.888 CUILesson[82227:303] found: http://www.4gamer.net 2013-06-06 19:52:16.888 CUILesson[82227:303] channel element: link : end 2013-06-06 19:52:16.889 CUILesson[82227:303] channel element: description : start 2013-06-06 19:52:16.889 CUILesson[82227:303] found: 日本最大級の総合ゲームサイトです。コンシューマゲームやオンラインゲーム,iPhone/iPadのゲーム,そしてPC のディープなハードウェア情報まで,日本だけでなく世界からも最新ゲームニュースをお届けします。ほかにも,ユ 2013-06-06 19:52:16.889 CUILesson[82227:303] found: ーザーレビューなどのクチコミ情報も充実。 2013-06-06 19:52:16.889 CUILesson[82227:303] channel element: description : end 2013-06-06 19:52:16.889 CUILesson[82227:303] channel element: dc:language : start 2013-06-06 19:52:16.890 CUILesson[82227:303] found: ja 2013-06-06 19:52:16.890 CUILesson[82227:303] channel element: dc:language : end 2013-06-06 19:52:16.890 CUILesson[82227:303] channel element: dc:rights : start 2013-06-06 19:52:16.890 CUILesson[82227:303] found: Copyright (C) 2000-2013 Aetas Inc. All Rights Reserved. 2013-06-06 19:52:16.890 CUILesson[82227:303] found: 本サ イト「4Gamer.net」の内容は,すべて無断転載を禁止します。ただし商用利用を 除き,リンクについてはその限りではありません。転載,商用利用,二次利用の 希望,ご意見などはwebmaster\@4gamer.netまで。 2013-06-06 19:52:16.890 CUILesson[82227:303] channel element: dc:rights : end 2013-06-06 19:52:16.891 CUILesson[82227:303] channel element: dc:date : start 2013-06-06 19:52:16.891 CUILesson[82227:303] channel element: dc:date : end 2013-06-06 19:52:16.891 CUILesson[82227:303] channel element: dc:publisher : start 2013-06-06 19:52:16.891 CUILesson[82227:303] found: Aetas 2013-06-06 19:52:16.891 CUILesson[82227:303] found: (株) 以下略
実行結果ログ(item)
2013-06-06 19:52:17.022 CUILesson[82227:303] item item start 2013-06-06 19:52:17.023 CUILesson[82227:303] item element: title : start 2013-06-06 19:52:17.023 CUILesson[82227:303] found: 「EVE Online」,探索コンテンツの再活性化を目指した大型アップデート「Odyssey」が実装に 2013-06-06 19:52:17.023 CUILesson[82227:303] item element: title : end 2013-06-06 19:52:17.023 CUILesson[82227:303] item element: link : start 2013-06-06 19:52:17.024 CUILesson[82227:303] found: http://www.4gamer.net/games/004/G000412/20130606085/ 2013-06-06 19:52:17.024 CUILesson[82227:303] item element: link : end 2013-06-06 19:52:17.024 CUILesson[82227:303] item element: dc:date : start 2013-06-06 19:52:17.024 CUILesson[82227:303] found: 2013-06-06T19:48:55+09:00 2013-06-06 19:52:17.024 CUILesson[82227:303] item element: dc:date : end 2013-06-06 19:52:17.024 CUILesson[82227:303] item element: description : start 2013-06-06 19:52:17.025 CUILesson[82227:303] found: CCPGamesがサービスを行うMMORPG\343\200\214EVEOnline」に,19回めとなる大型アップデート「Odyssey」実装されたことが,本日(2013年6月6日)ネクソンから発表された。探索コンテンツ再活性化を目指した今回のアップデート。新機能として 2013-06-06 19:52:17.026 CUILesson[82227:303] found: ,星間に隠された宝物や遺物といったものを発見するスキャナ「センサーオーバーレイ」が導入されるなどしている。 2013-06-06 19:52:17.026 CUILesson[82227:303] item element: description : end 2013-06-06 19:52:17.026 CUILesson[82227:303] item item end 2013-06-06 19:52:17.027 CUILesson[82227:303] item item start 2013-06-06 19:52:17.027 CUILesson[82227:303] item element: title : start 2013-06-06 19:52:17.027 CUILesson[82227:303] found: 「『真・女神転生IV」,DLC第3弾が配信。公式サイトにて詳細が公開 2013-06-06 19:52:17.027 CUILesson[82227:303] item element: title : end 2013-06-06 19:52:17.027 CUILesson[82227:303] item element: link : start 2013-06-06 19:52:17.027 CUILesson[82227:303] found: http://www.4gamer.net/games/166/G016690/20130606086/ 2013-06-06 19:52:17.028 CUILesson[82227:303] item element: link : end 2013-06-06 19:52:17.028 CUILesson[82227:303] item element: dc:date : start 2013-06-06 19:52:17.028 CUILesson[82227:303] found: 2013-06-06T19:39:13+09:00 2013-06-06 19:52:17.030 CUILesson[82227:303] item element: dc:date : end 2013-06-06 19:52:17.030 CUILesson[82227:303] item element: description : start 2013-06-06 19:52:17.030 CUILesson[82227:303] item element: description : end 2013-06-06 19:52:17.030 CUILesson[82227:303] item item end 2013-06-06 19:52:17.030 CUILesson[82227:303] item item start 以下略
ログを見ていくと、パーサーが開始/終了タグを見ているっぽいのがわかる。
この仕組みを利用して、必要なデータを確保することにしよう
以下次号