I'm trying to write a simple RSS reader for the iPhone, and it appeared to be working fine, until I started working with Instruments, and discovered my App is leaking massive amounts of memory.
I'm using the NSXMLParser class to parse an RSS feed. My memory leaks appear to be originating from the overridden delegate methods:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
and
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
I'm also suspicious of the code that populates the cells from my parsed data, I've included the code from those methods and a few other key ones, any insights would be greatly appreciated.
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([self.currentElement isEqualToString:@"title"]) {
[self.currentTitle appendString:string];
} else if ([self.currentElement isEqualToString:@"link"]) {
[self.currentURL appendString:string];
} else if ([self.currentElement isEqualToString:@"description"]) {
[self.currentSummary appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:@"item"]) {
//asdf
NSMutableDictionary *item = [[NSMutableDictionary alloc] init];
[item setObject:currentTitle forKey:@"title"];
[item setObject:currentURL forKey:@"URL"];
[item setObject:currentSummary forKey:@"summary"];
[self.currentTitle release];
[self.currentURL release];
[self.currentSummary release];
[self.stories addObject:item];
[item release];
}
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
// Set up the cell
int index = [indexPath indexAtPosition: [indexPath length] - 1];
CGRect contentRect = CGRectMake(8.0, 4.0, 260, 20);
UILabel *textLabel = [[UILabel alloc] initWithFrame:contentRect];
if (self.currentLevel == 0) {
textLabel.text = [self.categories objectAtIndex: index];
} else {
textLabel.text = [[self.stories objectAtIndex: index] objectForKey:@"title"];
}
textLabel.textColor = [UIColor blackColor];
textLabel.font = [UIFont boldSystemFontOfSize:14];
[[cell contentView] addSubview: textLabel];
//[cell setText:[[stories objectAtIndex: storyIndex] objectForKey: @"title"]];
[textLabel autorelease];
return cell;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
if ([elementName isEqualToString:@"item"]) {
self.currentTitle = [[NSMutableString alloc] init];
self.currentURL = [[NSMutableString alloc] init];
self.currentSummary = [[NSMutableString alloc] init];
}
if (currentElement != nil) {
[self.currentElement release];
}
self.currentElement = [elementName copy];
}
- (void)dealloc {
[currentElement release];
[currentTitle release];
[currentURL release];
[currentSummary release];
[currentDate release];
[stories release];
[rssParser release];
[storyTable release];
[super dealloc];
}
// Override to support row selection in the table view.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here -- for example, create and push another view controller.
// AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];
int index = [indexPath indexAtPosition: [indexPath length] - 1];
if (currentLevel == 1) {
StoryViewController *storyViewController = [[StoryViewController alloc] initWithURL:[[stories objectAtIndex: index] objectForKey:@"URL"] nibName:@"StoryViewController" bundle:nil];
[self.navigationController pushViewController:storyViewController animated:YES];
[storyViewController release];
} else {
RootViewController *rvController = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:nil];
rvController.currentLevel = currentLevel + 1;
rvController.rssIndex = index;
[self.navigationController pushViewController:rvController animated:YES];
[rvController release];
}
}