2012-07-03 22 views
5

Estoy usando NSXmlParser para analizar a través de un RSS Feed. Todo está funcionando bien hasta ahora.Use NSXMLParser para analizar solo las primeras diez publicaciones, luego analice el siguiente lote por separado

Anticipo que el feed rss eventualmente contenga docenas/cientos de publicaciones. Mi solución actual es leer todo el feed rss y mostrar los resultados. Sin embargo, solo quiero leer las primeras diez publicaciones (para evitar que analice potencialmente cientos de elementos). Luego, más adelante (por ejemplo, cuando el usuario llegue al final de la tabla) para analizar las siguientes diez publicaciones.

Así que mi pregunta es ¿cómo iba a analizar los primeros diez puestos, a continuación, analizar los próximos diez puestos, entonces los próximos diez puestos y así sucesivamente ...

Aquí es lo que estoy utilizando para obtener todos los mensajes:

- (void)parseXMLFileAtURL:(NSString *)URL 
{ 
    myArray = [[NSMutableArray alloc] init]; 

    //convert the path to a proper NSURL or it won't work 
    NSURL *xmlURL = [NSURL URLWithString:URL]; 

    rssParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL]; 
    [rssParser setDelegate:self]; 
    [rssParser parse]; 

} 

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError { 
    //error 
} 

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{    

    currentElement = [elementName copy]; 

    if ([elementName isEqualToString:@"item"]) { 
     //clear out our story item caches... 
     item = [[NSMutableDictionary alloc] init]; 

    } 

} 

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{  

    if ([elementName isEqualToString:@"item"]) { 
     // save values to an item, then store that item into the array... 
    } 

} 

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ 

    // save the characters for the current item... 

} 

- (void)parserDidEndDocument:(NSXMLParser *)parser { 

    [myTable reloadData]; 

} 

Respuesta

0

Puede llamar al [rssParser abortParsing] para detener el análisis sintáctico. Después de detenerlo, debe cortar manualmente la primera parte del xml. O dile al servicio web de alguna manera. NSXMLParser no le dará acceso para saltar allí.

0

Sin duda hacer un recuento var en su cabecera de la clase:

... 
@private 
    NSUInteger rssCounter; 
... 
@property (nonatomic, assign) NSUInteger rssCounter; 
... 

En sus delegados método init:

rssCounter = 0; 

Después, simplemente incrementar esta variable cada vez que se pulsa el final de un elemento, y luego como indicado por @Metalmi, utilice el análisis abortado en un bloque if else al iniciar un elemento.

Después de eso, crea un método que restablezca la variable a 0 cuando necesites cargar 10 más, a la que puedes llamar cuando necesites activar todo el proceso nuevamente.

Algo así como:

- (void)restartParsing:(NSString *)url 
{ 
    rssCounter = 0 
    [self parseXMLFileAtURL:url]; 
} 

Espero que esto ayude.

+0

Supongo que esto causará problemas de rendimiento al analizar la segunda mitad de xml, de lo contrario, será correcto analizarlo todo en un solo paso –

+0

@MarkPervovskiy No sé por qué esto podría causar problemas de rendimiento: ¿podría aclarar? – Ben

+0

El análisis de XML es una operación lenta, y puede tomar cualquier cantidad de tiempo, especialmente cuando xml contiene "cientos de mensajes". Por lo tanto, su solución lleva a analizar primero las 10 publicaciones, luego las primeras 20, luego las primeras 30 y así sucesivamente. En un momento, el usuario verá cómo se congela su yo durante medio segundo. –

7

En una respuesta de estilo diferente de las otras, quiero contribuir que si su analizador está tardando tanto en analizar que la diferencia entre 10 y 100 es una cantidad medible humanamente significativa, entonces está haciendo algo mal. Es probablemente la mejor manera:

  1. perfil de su código de análisis para encontrar la desaceleración (o encontrar una biblioteca XML con más prestaciones)
  2. Analizar todo el lote en un subproceso de fondo
  3. Sólo mostrar el primer 10 a la usuario,
  4. Muestra el resto de la memoria sobre la marcha.

Es una doble victoria, porque el análisis que a la vez hace que para el código más simple y menos errores, y "carga" (mostrando) un RSS "página" uno a la vez será la velocidad del rayo y sus usuarios les encantará usted (vea Instagram para ejemplos sobre velocidad de falsificación)

+0

Definitivamente esto. Desea utilizar nuestro buen amigo 'dispatch_async'. Si no estás familiarizado con GCD, te sugiero que veas los videos de la WWDC sobre el tema y te prepares para darte un respiro. –

0

Estoy de acuerdo con @coneybeare, parece ser la forma correcta de analizar xml en el hilo de fondo y almacenar el resultado en la memoria.

Sin embargo, si todavía quiere analizar XML "página por página" puede hacerlo mediante el uso de xmlParseChunklibxml (ver XMLPerformance sample por ejemplo). Tendrá que calcular manualmente los artículos y almacenar el excedente en alguna parte, pero supongo que es la funcionalidad más cercana que puede obtener de la caja.

Otra forma es tomar cualquier analizador XML de código abierto libre Objective-C (puede ser incluso DOM-analizador, como el ejemplo TBXML) y romper su bucle de análisis interno de la manera que más le convenga.

Cuestiones relacionadas