2009/09/17

[Objective-C][iPhone sdk]昨日のajaxの続き

昨日、rssをパースして、表示するプログラムを書きました。

で、問題となっていたのは、文字は取得できるものの、きちんと表示されないことでした。
(途中で、分割されてしまう現象がありました。)

他のrssでは、同様の現象が起きないだろーっと、おもいっきり、rssのせいにしていたのですが、他のrssを使っても、同様の現象が発生したので、明らかにプログラム上のバグでした。

そんでもって、今日、なんとなーく、プログラムしていたら、きちんとコンテンツを取得できたので、備忘録をかねて書いていきたいと思います。

まず、根本的に間違っていたのが、
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
メソッドの解釈。

あるタグ内にあるコンテンツ(文字列)を一回で取得するのかなーっと認識していたのですが、どうやら、そもそもそれが間違いみたいでした。

Xcodeのドキュメントをのぞいてみると、同メソッドはこんな感じで書かれている。

parser:foundCharacters:
Sent by a parser object to provide its delegate with a string representing all or part of the characters of the current element.

via:NSXMLParser Class Reference

問題となるのは、「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;
}

}

これで実行してみた結果、下の画像を得ることができました。

Photobucket
キタ!!

後は、タイトルを加工して、ヘッダーとして表示すればオッケー♪

tempString = [[NSMutableString alloc] init];
の部分は、
tempString = [[NSMutableString alloc] initWithCapacity:0];
でもいいみたいんだけど、ちょっとメソッドの使い方がなー。。。

さらなる改良点として、iPod touchなどでは常にネットに接続できるわけではないので、ネットに接続していない時にも、コンテンツが表示できるようにしたいなー。

おそらくキャッシュを使えば、この問題はクリアーできそうなのですが、まだ未体験ゾーンです。

1 件のコメント:

  1. 全くの別件ですが、公開されているgoo辞書ガジェットのWikipedia検索が機能していません。
    登録者が多いようなので、私も含め不便で残念な思いをしている方が多いと思います。
    修正していただけると嬉しいのですが。
    お忙しいところ申し訳ないです。

    返信削除