2010-02-24 1 views
1

iPhone 용 간단한 RSS 리더를 작성하려고하는데, Instruments와 작업하기 전에는 제대로 작동하는 것으로 보였습니다. 내 앱에서 방대한 양의 메모리가 누수되고 있음을 발견했습니다. .RSS 리더에서 메모리 누수에 대한 도움이 필요합니다.

RSS 피드를 구문 분석하기 위해 NSXMLParser 클래스를 사용하고 있습니다. 내 메모리 누수는 오버라이드 (override) 대리자 메서드에서 발생하는 것으로 나타났습니다 :

- (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의 "빌드 및 분석"명령을 사용해보십시오. 그러면 해당 누수가 발견 될 가능성이 있습니다. –

+0

귀하의 의견을 보내 주셔서 감사합니다. 실제로 Xcode 3.1을 사용하고 있으므로 해당 기능을 사용할 수 없지만 Clang을 다운로드하여 터미널에서 프로젝트에 실행하면 오류가 발생하지 않습니다. – Stilton

답변

0

나는 내 문제를 파악, 내 메모리 누수는 모두이 문 막아야 :

이가 2 씩 증가하는 이야기의 수를 유지됩니다
self.stories = [[NSMutableArray alloc] init];

, setter가 새로 할당 된 배열을 유지하기 때문에.

나는이 하나 이상의 문을 교체하고 내 문제 해결 :

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

코드를 수정하는 또 다른 방법이

self.stories = [NSMutableArray arrayWithCapacity:10]; 

self.stories = [NSMutableArray alloc] init]; 

교체입니다 arrayWithCapacity 메서드는 자동으로 릴리즈되므로 수동으로 release를 호출 할 필요가 없습니다. (이것은 다른 클래스, 즉setWithCapacity, stringWithFormat 등)

감사합니다, 샘


PS 질문을 돕고 있지만,이 라인은 조금 특이한 보지 :

self.currentTitle = nil; 
: 당신은 아마이 일을해야

[self.currentTitle release]; 

그러면 currentTitle이 코드와 동일하게 출시되지만 설정됩니다. 실수로 다시 사용할 수 없다는 뜻입니다!