2010-02-24 64 views
1

我正在嘗試爲iPhone編寫一個簡單的RSS閱讀器,它似乎工作正常,直到我開始使用樂器,並且發現我的應用程序泄漏了大量內存。在RSS閱讀器中需要內存泄漏幫助

我正在使用NSXMLParser類來解析RSS提要。我的內存泄漏看起來是從覆蓋的委託方法始發:

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

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

我也懷疑是不是從我的分析數據填充單元格中的代碼,我已經包含了來自這些方法和其他一些關鍵方法的代碼,任何見解都將不勝感激。

 

- (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]; 
    } 
} 
 

+0

我瀏覽了你的代碼,沒有發現我明顯的錯誤;你可能想嘗試Xcode的「構建和分析」命令,它應該指向你找到的任何潛在的泄漏。 – 2010-02-24 00:09:49

+0

感謝您的評論,我實際上使用XCode 3.1,所以這個功能對我來說是不可用的,但是我沒有下載Clang並從終端運行在我的項目上,它沒有發現任何錯誤。 – Stilton 2010-02-24 00:18:46

回答

0

我想通了,我的問題,我所有的內存泄漏從這句話朵朵:

self.stories = [[NSMutableArray alloc] init];

這將導致保留故事的計數遞增2,因爲setter調用保留在新分配的數組上。

我替換爲一個以上的語句,它解決了我的問題:

NSMutableArray *array = [[NSMutableArray alloc] init]; 
self.stories = array; 
[array release];
0

修復代碼的另一種方法是這樣與

self.stories = [NSMutableArray arrayWithCapacity:10]; 

更換

self.stories = [NSMutableArray alloc] init]; 

arrayWithCapacity方法是autoreleased,所以你不需要手動調用release。 (對於其他類也是如此setWithCapacity,stringWithFormat等)

謝謝,山姆


PS幫不了你的問題,但這些線條看起來有點不尋常:

[self.currentTitle release]; 

或許你也應該這樣做:

self.currentTitle = nil; 

這將釋放currentTitle與您的代碼一樣,但它也會設置它到零這意味着你不能再次誤用它!