iPhone で NSXMLParser を使用して XML を解析する場合、奇妙な問題があります。アプリを起動するときに、バックグラウンドで RSS フィードによって入力される 4 つのテーブル ビューをプリロードしたいと考えています。
テーブルビューを 1 つずつ初期化すると、すべての読み込み、解析、および表示が魅力的に機能します。しかし、すべてのビューを一度に (同時に) 初期化しようとすると、XML パーサー インスタンスが互いに干渉しているように見えます。1 つの XML-Feed からのデータが、属していない他の xml-parser インスタンスに「ブロードキャスト」されます。例:「これは私の名前です」という「チームメンバー」の項目があります。このバグが発生すると、別の xml フィードからの文字列が追加されます。つまり、"This is my name58" という結果になります。ここで、58 は他のビューからの何かのチャート位置です。「58」は、他のインスタンスでは見逃されているようです。
このバグは、NSXMLParser-delegate メソッドが原因で発生しているように見えます。
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if (!currentStringValue) {
currentStringValue = [[NSMutableString alloc] initWithCapacity:50];
}
[currentStringValue appendString:string];
}
この場合、「偶然にも」バイトが、属していない文字列に追加されます。
奇妙なことに、NSXMLParser のすべてのインスタンスは一意であり、独自の ViewController にアタッチされた独自のデリゲートを持っています。すべての解析要求は、独自の (これも一意の名前の) Autorelease-pool を使用して、独自のバックグラウンド タスクを生成します。
ViewController で次のように NSXMLParser を呼び出しています。
// prepare XML saving and parsing
currentStringValue = [[[NSMutableString alloc] initWithCapacity:50] retain];
charts = [[NSMutableArray alloc] init];
NSURL *url = [[NSURL alloc] initWithString:@"http://(SOME XML URL)"];
xmlParser = [[[NSXMLParser alloc] initWithContentsOfURL:url] retain];
//Set delegate
[xmlParser setDelegate:self];
//loading indicator
progressWheel = [[[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(150.0,170.0,20.0,20.0)] autorelease];
progressWheel.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
[self.view addSubview:progressWheel];
[progressWheel startAnimating];
// start loading and parsing the xml-feed in the background
//[self performSelectorInBackground:@selector(parse:) withObject:xmlParser]; -> I also tried this
[NSThread detachNewThreadSelector:@selector(parse:) toTarget:self withObject:xmlParser];
これは、フィードを解析するバックグラウンド タスクの 1 つです。
-(void)parse:(NSXMLParser*)myParser {
NSAutoreleasePool *schedulePool = [[NSAutoreleasePool alloc] init];
BOOL success = [myParser parse];
if(success) {
NSLog(@"No Errors. xmlParser got: %@", myParser);
(POST-PROCESSING DETAILS OF THE DATA RETURNED)
[self.tableView reloadData];
} else {
NSLog(@"Couldn't initalize XMLparser");
}
[progressWheel stopAnimating];
[schedulePool drain];
[myParser release];
}
この問題の原因は何ですか? バックグラウンド タスクを正しい方法で呼び出していますか? すべての XML-Parser が独自の一意のインスタンスを持っているのに、なぜこのバグが近づいているのでしょうか?