昨日、rssをパースして、表示するプログラムを書きました。
で、問題となっていたのは、文字は取得できるものの、きちんと表示されないことでした。
(途中で、分割されてしまう現象がありました。)
他のrssでは、同様の現象が起きないだろーっと、おもいっきり、rssのせいにしていたのですが、他のrssを使っても、同様の現象が発生したので、明らかにプログラム上のバグでした。
そんでもって、今日、なんとなーく、プログラムしていたら、きちんとコンテンツを取得できたので、備忘録をかねて書いていきたいと思います。
まず、根本的に間違っていたのが、
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
メソッドの解釈。
あるタグ内にあるコンテンツ(文字列)を一回で取得するのかなーっと認識していたのですが、どうやら、そもそもそれが間違いみたいでした。
Xcodeのドキュメントをのぞいてみると、同メソッドはこんな感じで書かれている。
parser:foundCharacters:
via:NSXMLParser Class Reference
Sent by a parser object to provide its delegate with a string representing all or part of the characters of the current element.
問題となるのは、「all or part」と書かれているところ。
partから、「部分的に」と訳すことができるのですが、昨日組んだプログラムを実行したところ、まがいなりもすべて取得できていました。
つまり、このメソッドは、同じタグ内に対して、何回か呼ばれて、文字列を取得しているということなのではないのかなーっということ。(どうして、一回ではなく、複数回にわけて、タグ内の文字列を取得しているのかは、リファレンスに記載されていないのでわかりませんが。)
最初に想定していた、一度に、いっぺんにコンテンツを取得するという勝手な解釈とは、全然、違っておりました。
(まー、リファレンスを読むとそれもできるみたいなのですが。)
以上から、メソッドの流れをまとめてみるとこんな感じ。
parser:didStartElement:namespaceURI:qualifiedName:attributes: (ある特定のタグに到着) ↓ parser:foundCharacters: (タグの下にある文字列を一部取得) ↓ parser:foundCharacters: (タグの下にある文字列を一部取得) ↓ parser:foundCharacters: (タグの下にある文字列を一部取得) ↓ parser:didEndElement:namespaceURI:qualifiedName: (閉じタグに到着) |
ここまでの流れがわかったので、後は、もう一度、リファレンスを読みながら、再度、プログラムを修正してみました。
/* TestAppDelegate.hに追加 */ NSMutableString *tempString; /* TestAppDelegate.mを修正 */ - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{ /* titleタグに到着 */ if([elementName isEqualToString:@"title"]){ appendflg = YES; /* それ以外のタグに到着した場合は、シカトします。 */ }else{ appendflg = NO; } } - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { if(appendflg == YES){ if (!tempString) { tempString = [[NSMutableString alloc] init]; } /* 文字列の追加 */ [tempString appendString:string]; } } - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { /* タイトルタグの場合 */ if([elementName isEqualToString:@"title"]){ [testviewcontroller.parsedData addObject:tempString]; [tempString release]; tempString = nil; } } |
これで実行してみた結果、下の画像を得ることができました。
キタ!!
後は、タイトルを加工して、ヘッダーとして表示すればオッケー♪
tempString = [[NSMutableString alloc] init];
の部分は、
tempString = [[NSMutableString alloc] initWithCapacity:0];
でもいいみたいんだけど、ちょっとメソッドの使い方がなー。。。
さらなる改良点として、iPod touchなどでは常にネットに接続できるわけではないので、ネットに接続していない時にも、コンテンツが表示できるようにしたいなー。
おそらくキャッシュを使えば、この問題はクリアーできそうなのですが、まだ未体験ゾーンです。
全くの別件ですが、公開されているgoo辞書ガジェットのWikipedia検索が機能していません。
返信削除登録者が多いようなので、私も含め不便で残念な思いをしている方が多いと思います。
修正していただけると嬉しいのですが。
お忙しいところ申し訳ないです。