Reputation: 11
Greetings,
I have a problem with adding an object from parser to mutable array. It was working fine until I moved MtableArray from AppDelegate to ViewController. This is where I call parser (MutableArray is inside this View also):
NSURL *url = [[NSURL alloc] initWithString:@"http://example.com"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
parser = [[XMLParser alloc] init];
[xmlParser setDelegate:parser];
[xmlParser parse];
...and this is inside parser where objects should be added:
if([elementName isEqualToString:@"Element"]) {
[viewController.marray addObject:parsedObj];
[parsedObj release];
parsedObj = nil;
}
marray is synthesized inside viewController. Parser is doing good job, I tried with NSLog, but marray.count is always (null). Please help!!!
Upvotes: 1
Views: 910
Reputation: 1
I tried a different approach and now I have two solutions and a problem with both of them. I have a XML parser that should add objects to NSMutableArray from where it has been called at first. Parser is working OK, but here is the problem. First approach:
I changed NSXMLParser's init method inside my XMLParser.m (mArray is for Mutable Array and):
- (XMLParser *) initXMLParser:(id)sender {
[super init];
mArray=(NSMutableArray *)sender;
return self;}
mArray in implementation file XMLParser.h:
@interface XMLParser : NSObject <NSXMLParserDelegate>{
NSMutableString *currentElementValue;
NSMutableArray *mArray;
Object *aObject;}
-(XMLParser *) initXMLParser:(id)sender;
@end
So, let's get to the part where we call XMLParser from ViewController.m:
mArray = [[NSMutableArray alloc] init];
NSURL *url = [[NSURL alloc] initWithString:@"http://www.a.com/some.xml"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
XMLParser *parser = [[XMLParser alloc] initXMLParser:self.mArray];
[xmlParser setDelegate:parser];
[xmlParser parse];
...and here is ViewController.h:
@class XMLParser;
@interface AccomodationSecondViewController : UIViewController{
@public NSMutableArray *mArray;}
@property (nonatomic, retain) NSMutableArray *mArray;
I'm not sure because this is first time I'm using public objects so... Anyway, this is the part inside XMLParser.m that should add objects:
//This is for closing bracket
if([elementName isEqualToString:@"Element"]) {
[mArray addObject:aObject];
[aObject release];
aObject=nil;}
So, the idea is to make mutable array mArray public inside ViewController and to send pointer to it to XMLParser. I know that this may be little unnatural, but I just want to get it to work.
My other idea is this: To send pointer of ViewController to XMLParser and do the rest. So, I changed initXMLParser:
- (XMLParser *) initXMLParser:(id)sender {
[super init];
viewController=(ViewController *)sender;
return self;}
and this is the part inside ViewController.m where I call my method:
XMLParser *parser = [[XMLParser alloc] initXMLParser:self];
then I add object:
[viewController.mArray addObject:aObject];
Why is this not working??!!
Upvotes: 0
Reputation: 2826
Have you verified that the marray property is non-nil? If it somehow hasn't been set properly then all of the insertions will be no-ops, and the the result of the count method will be nil.
Now that you've posted more code, this line is your problem:
[marray init];
You need to alloc/init a new NSMutableArray; this line is simply sending the init message to nil.
Upvotes: 1
Reputation: 11
Here is some more code: ViewController.h
#import <UIKit/UIKit.h>
@class XMLParser;
@interface ViewController : UIViewController{
NSMutableArray *marray;
XMLParser *parser;
}
@property (nonatomic, retain) NSMutableArray *marray;
@property (nonatomic, retain) XMLParser *parser;
@end
ViewController.m
#
import "ViewController.h"
#import "ParsedObj.h"
#import "XMLParser.h"
@synthesize marray;
@synthesize parser;
(...)
-(void)search:(id)sender{
[marray init];
NSURL *url = [[NSURL alloc] initWithString:@"http://example.com"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
parser = [[XMLParser alloc] init];
[xmlParser setDelegate:parser];
[xmlParser parse];
(...)
@end
XMLparser.h:
#import <UIKit/UIKit.h>
@class ViewController, ParsedObj;
@interface XMLParser : NSObject <NSXMLParserDelegate>{
NSMutableString *currentElementValue;
ViewController *viewController;
ParsedObj *parsedObj;
}
@end
..and XMLparser.m:
#import "XMLParser.h"
#import "ViewController.h"
#import "ParsedObj.h"
@implementation XMLParser
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:@"Root"]) {
//Initialize the array.
viewController.marray = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:@"Element"]) {
//Initialize the hotel.
parsedObj = [[ParsedObj alloc] init];
//Extract the attribute here.
parsedObj.ID = [[attributeDict objectForKey:@"id"] integerValue];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if(!currentElementValue)
currentElementValue = [[NSMutableString alloc] initWithString:string];
else
[currentElementValue appendString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if([elementName isEqualToString:@"Root"])
return;
//There is nothing to do if we encounter the Books element here.
//If we encounter the Book element howevere, we want to add the book object to the array
// and release the object.
if([elementName isEqualToString:@"Element"]) {
[accomodationController.marray addObject:parsedObj];
parsedObj = nil;
}
else {
NSString *cValue=[currentElementValue stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[parsedObj setValue:cValue forKey:elementName];
}
[currentElementValue release];
currentElementValue = nil;
}
- (void)dealloc {
[parsedObj release];
[currentElementValue release];
[super dealloc];
}
@end
Upvotes: 0
Reputation: 15115
Try like this,
[viewController.marray addObject:[parsedObj copy]];
Upvotes: 1
Reputation: 2102
Can you post more code?
If you are inside view controller when marray is being called, you shouldn't have to call viewController.marray
, just marray
One suggestion, from my experience in parsing, is to use an NSMutableDictionary instead of an array..so, for instance:
- (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 story item caches
item = [[NSMutableDictionary alloc] init];
currentTitle = [[NSMutableString alloc] init];
currentAddress = [[NSMutableString alloc] init];
currentCity = [[NSMutableString alloc] init];
currentState = [[NSMutableString alloc] init];
currentZip = [[NSMutableString alloc] init];
currentId = [[NSMutableString alloc] init];
}
}
and then to add everything:
- (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
[item setObject:currentTitle forKey:@"title"];
[item setObject:currentAddress forKey:@"address"];
[item setObject:currentCity forKey:@"city"];
[item setObject:currentState forKey:@"state"];
[item setObject:currentZip forKey:@"zip"];
[item setObject:currentId forKey:@"id"];
// venues is the mutable array
[venues addObject:[item copy]];
} else {
return;
}
}
Now my mutable array has all the elements I need, and I can do various things with it (like reload a table cell). The above code has been tested and verified as working.
Upvotes: 0