views:

70

answers:

3

I am newbie to Iphone Application development. Please help me. I am sorry if I am wrong. I have following declarations:

 //.h file:
    NSMutableArray *dataArray;
    NSMutableDictionary *item;

    //.m file
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{            
        currentElement = [elementName copy];
        if ([elementName isEqualToString:@"table"]){
        item = [[NSMutableDictionary alloc] init];
        currentEid = [[NSMutableString alloc] init];
        currentEname = [[NSMutableString alloc] init];
        currentEurl = [[NSMutableString alloc] init];
        }
        //NSLog(@"didStartElement");
        }

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

        if ([elementName isEqualToString:@"table"]) {
            // save values to an item, then store that item into the array...
            [item setObject:currentEname forKey:@"ename"];
            //NSLog(@"%@",item);
            [self.dataArray addObject:[item copy]];
            NSLog(@"%@",dataArray);
            }
    }

    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
        if ([currentElement isEqualToString:@"eid"]) {
            [currentEid appendString:string];
        } else if ([currentElement isEqualToString:@"ename"]) {
            [currentEname appendString:string];
            //NSLog(@"%@",currentEname);
        } else if ([currentElement isEqualToString:@"eurl"]) {
            [currentEurl appendString:string];
        } 
        //  NSLog(@"foundCharacters");
    }

I get null values for the NSMutableArray(dataArray) when displayed. How to solve it? Or else tell me the way to display the NSMutableDicitonary data in table view cells.

Thanks in Advance.. :)

A: 

You need to make sure that dataArray is created. Put this in your class's init method or wherever else it would be appropriate:

dataArray = [[NSMutableArray alloc] init];

Also, I hope your iPhone has a lot of memory, as your code is leaking a fair bit.

dreamlax
Hey Thanks!!! DreamLax...Its working now.But I dont know about leaking.. What is it???Will you please help me again. I would like to display the same dataArray in the table view cells.How to do it??
Rohit
iphone doesn't have a automatic garbage collector and the amount of memory availble to your application is very small.So for every alloc | retain | copy you have to have a release somewhere in your application.For effective memory management you can find a lots of document over web and also in this site.
raaz
A: 

To solve the leaks dreamlax mentioned, you need to add code in front of this:

item = [[NSMutableDictionary alloc] init];
        currentEid = [[NSMutableString alloc] init];
        currentEname = [[NSMutableString alloc] init];
        currentEurl = [[NSMutableString alloc] init];

With something like this:

[item release]; [currentEid release]; [currentEname release]; [currentEurl release];
item = [[NSMutableDictionary alloc] init];
            currentEid = [[NSMutableString alloc] init];
            currentEname = [[NSMutableString alloc] init];
            currentEurl = [[NSMutableString alloc] init];

And also reelase them when you are done parsing...

Don't check my answer as correct though, dreamlax deserves the credit for pondering the code...

For populating a UITableView, you really need to work through some of the UITableView examples and see how they load data.

Kendall Helmstetter Gelner
I personally would avoid having 4 separate statements on one line.
Shaggy Frog
Normally I would not do that either, I just wanted to quickly illustrate they should be free... however it's quite common to put something like [item release]; item = nil on a single line as they are intimately related.
Kendall Helmstetter Gelner
A: 

In your code, you have a number of allocs. These need to be balanced with release. You also have a copy that needs to be balanced with a release. If you don't release these objects, you will end up allocating new objects over and over, and you will eventually run out of memory.

What you need to do is figure out where in your code is a suitable place to release them. When you no longer need the objects that you allocated, you should release them. In your case, it may be sensible to add the following code in your - (void)parser:didEndElement:namespaceURI:qualifiedName: method, like this:


- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{     
        if ([elementName isEqualToString:@"table"]) {
            // save values to an item, then store that item into the array...
            [item setObject:currentEname forKey:@"ename"];
            //NSLog(@"%@",item);
            [self.dataArray addObject:[[item copy] autorelease]];
            NSLog(@"%@",dataArray);
            }
        [currentEid release];
        [currentEname release];
        [currentEurl release];
    }

Note that I also added an autorelease to your copy. copy useful because it creates an immutable copy of your object, which in this particular case might be what you're after. However, when you create a copy, you are the owner of the copy and you are responsible for releasing it. Your dataArray array will take ownership of your item copy when you add it with addObject:, but you must still relinquish your ownership by releasing it. However, we can't release it before we give it to the array, otherwise the item copy will be deallocated before it is given to dataArray, so it is auto-released instead. An autoreleased object is guaranteed to survive for at least the remainder of the method.

An alternative to autoreleasing is to manually keep track of the item copy, like this:


- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{     
        if ([elementName isEqualToString:@"table"]) {
            NSDictionary *itemCopy;
            // save values to an item, then store that item into the array...
            [item setObject:currentEname forKey:@"ename"];
            //NSLog(@"%@",item);
            itemCopy = [item copy];
            [self.dataArray addObject:itemCopy];
            [itemCopy release];
            NSLog(@"%@",dataArray);
            }
        [currentEid release];
        [currentEname release];
        [currentEurl release];
    }
dreamlax