I am parsing XML with NSXMLParser and I have some NSMutableArrays (instance variables) in my app. When I parse the XML file, I build objects with the values of the XML elements, and set my array with those objects.
In the moment that I set my array with those objects I can see the values of them. But once I have finished parsing the XML I want to retrieve those values and the array is now empty.
Here is a part of my code:
//STHelpViewController.h
#import <UIKit/UIKit.h>
@class SoftokeniPhoneAppDelegate, FAQ;
@interface STHelpViewController : UIViewController {
UIView *viewAnswer;
UINavigationBar *answerTitle;
UIButton *answerDescription;
NSArray *answersArray;
NSMutableArray *faqs; //THIS IS MY ARRAY WITH THE PROBLEM
NSMutableString *currentElementValue;
FAQ *aFAQ;
NSString* Answer1;
NSString* Answer2;
NSString* Answer3;
NSString* Answer4;
}
@property (nonatomic, retain) IBOutlet UIView *viewAnswer;
@property (nonatomic, retain) IBOutlet UINavigationBar *answerTitle;
@property (nonatomic, retain) IBOutlet UIButton *answerDescription;
@property (nonatomic, retain) NSMutableArray *faqs;
@property (nonatomic, retain)NSString* Answer1;
@property (nonatomic, retain)NSString* Answer2;
@property (nonatomic, retain)NSString* Answer3;
@property (nonatomic, retain)NSString* Answer4;
@end
//STHelpViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [[NSURL alloc] initWithString:@"http://clientes.imit.cl/MovilPass/faq.xml"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
//Initialize the delegate.
STHelpViewController *parser = [[STHelpViewController alloc] initXMLParser];
//Set delegate
[xmlParser setDelegate:parser];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
if(success){
NSLog(@"F.A.Q. loaded from XMl file");
//HERE IS THE PROBLEM. AT THIS PART XCODE SAYS THAT faqs(my array) IS EMPTY
Answer1 = [[[faqs objectAtIndex:0] valueForKey:@"Respuesta"]description];
Answer2 = [[[faqs objectAtIndex:1] valueForKey:@"Respuesta"]description];
Answer3 = [[[faqs objectAtIndex:2] valueForKey:@"Respuesta"]description];
Answer4 = [[[faqs objectAtIndex:3] valueForKey:@"Respuesta"]description];
answersArray = [[NSArray alloc] initWithObjects:Answer1,Answer2,Answer3,Answer4,nil];
}
else
{
NSLog(@"Error loading XML file for F.A.Q. Default data loaded instead.");
answersArray = [[NSArray alloc]
initWithObjects:@"El Movilpass es una nueva herramienta de Bci Móvil que le permitirá obtener la clave 开发者_开发知识库de ocho dígitos desde su celular, sin tener que llevar el dispositivo electrónico. Regístrese para recibir la aplicación, cárguela en su Iphone y sincronícela.",
@"El Movilpass es igual de válido que el dispositivo electrónico. Sólo debe sincronizarlo correctamente en su celular, siguiendo uno a uno los pasos que le indiquen.",
@"Para sincronizar, presione el botón “Ajustes”, luego “Sincronizar” y obtendrá los siguientes pasos:\n \n Ingrese a su banca Internet. \n Entre a Seguridad y Emergencia. \n Click en Movilpass. \n Seleccione el botón 'Sincronizar'.",
@"Si se le perdió su TELEFONO, lo primero que debe hacer es llamar al 600 8242424 para que lo bloqueen. Una vez que obtenga el nuevo aparato, podrá solicitar nuevamente su Movilpass.",
nil];
}
}
- (STHelpViewController *) initXMLParser {
[super init];
//appDelegate = (SoftokeniPhoneAppDelegate *)[[UIApplication sharedApplication] delegate];
return self;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:@"PreguntasFrecuentes"]) {
faqs = [[NSMutableArray new]retain];
}
else if([elementName isEqualToString:@"Item"])
{
aFAQ = [[FAQ alloc] init];
aFAQ.itemID = [[attributeDict objectForKey:@"id"] integerValue];
NSLog(@"Leyendo valor de atributo id: %i", aFAQ.itemID);
}
NSLog(@"Procesando Elemento: %@", elementName);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if(!currentElementValue)
currentElementValue = [[NSMutableString alloc] initWithString:string];
else
[currentElementValue appendString:string];
NSLog(@"Procesando Valor: %@", currentElementValue);
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if([elementName isEqualToString:@"PreguntasFrecuentes"])
return;
if([elementName isEqualToString:@"Item"]) {
[faqs addObject:aFAQ];
[aFAQ release];
aFAQ = nil;
}
else
{
[aFAQ setValue:currentElementValue forKey:elementName];
}
[currentElementValue release];
currentElementValue = nil;
//IF I PRINT MY ARRAY HERE, I CAN SEE THE VALUES
}
What could I be doing wrong?
You instantiate faqs = [[NSMutableArray new]retain];
on every didStartElement
call. It seems weird to me. You should move faqs = [[NSMutableArray new]retain];
to your viewDidLoad
.
Moreover, I don't see the necessity of retain
there.
1. In viewDidLoad you're allocating another STHelpViewController for no good reason. Do this instead,
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [[NSURL alloc] initWithString:@"http://clientes.imit.cl/MovilPass/faq.xml"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[url release];
//I am the delegate
[xmlParser setDelegate:self];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
//NSLog(@"Count My FAQ %d", [[self faqs] count]); Uncomment for debugging.
...
}
2. If you don't use self you have to fix initXMLParser. You must always use the designated initializer of you super class and assign to the ivar self. Like so,
- (STHelpViewController *) initXMLParser {
if(self = [super init]) {
//alloc and init any ivar you want
}
return self;
}
And then do this,
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [[NSURL alloc] initWithString:@"http://clientes.imit.cl/MovilPass/faq.xml"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[url release];
//Initialize the delegate.
STHelpViewController *parser = [[STHelpViewController alloc] initXMLParser];
//Set delegate
[xmlParser setDelegate:parser];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
//Get results from parser
NSArray parserFAQs = [parser faqs];
[parser release];
//NSLog(@"Count Parser's FAQ %d", [parserFAQs count]); Uncomment for debugging.
...
}
精彩评论