iPhone: парсинг нескольких XML с помощью NSXMLParser в фоновом режиме мешает друг другу

У меня странная проблема, когда дело доходит до синтаксического анализа XML с помощью NSXMLParser на iPhone. При запуске приложения я хочу предварительно загрузить 4 табличных представления, которые заполняются RSS-потоками в фоновом режиме.

Когда я инициирую просмотр таблиц один за другим, загрузка, синтаксический анализ и отображение все работает как шарм. Но когда я пытаюсь запустить все представление сразу (одновременно), мне кажется, что экземпляры XML-парсера мешают друг другу. Каким-то образом данные из одного XML-фида «транслируются» в другие экземпляры xml-парсера, которым они не принадлежат. Пример: есть элемент «член команды» с надписью «Это мое имя». Когда возникает эта ошибка, добавляется строка из другого xml-фида, то есть приводит к: «Это мое имя58», где 58 - позиция на диаграмме для чего-то из другого представления. «58», кажется, не хватает тогда на другом экземпляре.

Мне кажется, что эта ошибка возникает из-за метода делегата NSXMLParser:

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    if (!currentStringValue) {
        currentStringValue = [[NSMutableString alloc] initWithCapacity:50];
    }
    [currentStringValue appendString:string];   
}

В этом случае «по совпадению» байты добавляются к строкам, которым они не принадлежат.

Странно то, что каждый экземпляр NSXMLParser уникален, имеет свои собственные уникальные делегаты, которые прикреплены к их собственному ViewController. Каждый запрос на синтаксический анализ порождает свою собственную фоновую задачу со своим собственным (также уникальным по имени) пулом автозапуска.

Я вызываю NSXMLParser в ViewController следующим образом:

// 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];

А это одна из фоновых задач по разбору ленты:

- (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-парсера есть свой уникальный экземпляр?


person nodepond    schedule 29.04.2010    source источник
comment
Строка currentStringValue = [[[NSMutableString alloc] initWithCapacity:50] retain]; неверна. Когда вы распределяете, вы сохраняете это. Тогда вы снова его сохраняете. Вы хотите использовать автозапуск вместо сохранения?   -  person lucius    schedule 29.04.2010


Ответы (2)


Вы не должны обновлять элементы пользовательского интерфейса (например, progressWheel) из фонового потока. Обновления пользовательского интерфейса должны выполняться в основном потоке.

Используйте -performSelectorOnMainThread:withObject:waitUntilDone: для обновления элементов пользовательского интерфейса из фонового потока.

person Alex Reynolds    schedule 29.04.2010
comment
О, похоже, это вызвало главную проблему в моем приложении. Проведу различные тесты, но вроде бы проблема решена. - person nodepond; 30.04.2010

Я выпустил RSS / Atom Parser для iPhone с открытым исходным кодом, который чрезвычайно упрощает чтение и анализ веб-каналов.

Вы можете настроить его для асинхронной загрузки данных или синхронно запустить его в фоновом потоке для сбора данных канала.

Надеюсь это поможет!

person Michael Waterfall    schedule 21.07.2010