2010-05-19 5 views
2

RSS 피드를 구문 분석하는 앱을 만들고 있습니다. 앱에는 피드의 요소에 대해 서로 다른 두 가지 유형의 피드가 있으므로 파싱하기 전에 각 피드의 요소 이름을 사용하는 NSXMLParser NSObject를 만들었습니다. 여기 내 코드입니다 :Iphone NSXMLParser NSCFString 메모리 누수

NewsFeedParser.h는

 
#import 


@interface NewsFeedParser : NSObject { 
    NSInteger NewsSelectedCategory; 
    NSXMLParser *NSXMLNewsParser; 
    NSMutableArray *newsCategories; 
    NSMutableDictionary *NewsItem; 
    NSMutableString *NewsCurrentElement, *NewsCurrentElement1, *NewsCurrentElement2, *NewsCurrentElement3; 
    NSString *NewsItemType, *NewsElement1, *NewsElement2, *NewsElement3; 
    NSInteger NewsNumElements; 
} 

- (void) parseXMLFileAtURL:(NSString *)URL; 
@property(nonatomic, retain) NSString *NewsItemType; 
@property(nonatomic, retain) NSString *NewsElement1; 
@property(nonatomic, retain) NSString *NewsElement2; 
@property(nonatomic, retain) NSString *NewsElement3; 
@property(nonatomic, retain) NSMutableArray *newsCategories; 
@property(assign, nonatomic) NSInteger NewsNumElements; 

@end 

NewsFeedParser.m

 
#import "NewsFeedParser.h" 


@implementation NewsFeedParser 

@synthesize NewsItemType; 
@synthesize NewsElement1; 
@synthesize NewsElement2; 
@synthesize NewsElement3; 
@synthesize newsCategories; 
@synthesize NewsNumElements; 

- (void)parserDidStartDocument:(NSXMLParser *)parser{ 

} 

- (void)parseXMLFileAtURL:(NSString *)URL 
{ 
    newsCategories = [[NSMutableArray alloc] init]; 

    URL = [URL stringByReplacingOccurrencesOfString:@" " withString:@""]; 
    URL = [URL stringByReplacingOccurrencesOfString:@"\n" withString:@""]; 
    URL = [URL stringByReplacingOccurrencesOfString:@" " withString:@""]; 

    //you must then convert the path to a proper NSURL or it won't work 
    NSURL *xmlURL = [NSURL URLWithString:URL]; 

    // here, for some reason you have to use NSClassFromString when trying to alloc NSXMLParser, otherwise you will get an object not found error 
    // this may be necessary only for the toolchain 
    [[NSURLCache sharedURLCache] setMemoryCapacity:0]; 
    [[NSURLCache sharedURLCache] setDiskCapacity:0]; 
    NSXMLNewsParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL]; 

    // Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks. 
    [NSXMLNewsParser setDelegate:self]; 

    // Depending on the XML document you're parsing, you may want to enable these features of NSXMLParser. 
    [NSXMLNewsParser setShouldProcessNamespaces:NO]; 
    [NSXMLNewsParser setShouldReportNamespacePrefixes:NO]; 
    [NSXMLNewsParser setShouldResolveExternalEntities:NO]; 

    [NSXMLNewsParser parse]; 
    [NSXMLNewsParser release]; 
} 


- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError { 
    NSString * errorString = [NSString stringWithFormat:@"Unable to download story feed from web site (Error code %i)", [parseError code]]; 
    NSLog(@"error parsing XML: %@", errorString); 

    UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:@"Error loading content" message:errorString delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
    [errorAlert show]; 
    [errorAlert release]; 
    [errorString release]; 
} 


- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{    

    NewsCurrentElement = [elementName copy]; 
    if ([elementName isEqualToString:NewsItemType]) 
    { 
     // clear out our story item caches... 
     NewsItem = [[NSMutableDictionary alloc] init]; 
     NewsCurrentElement1 = [[NSMutableString alloc] init]; 
     NewsCurrentElement2 = [[NSMutableString alloc] init]; 
     if(NewsNumElements == 3) 
     { 
      NewsCurrentElement3 = [[NSMutableString alloc] init]; 
     } 

    } 

} 

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

    if ([elementName isEqualToString:NewsItemType]) 
    { 
     // save values to an item, then store that item into the array... 
     [NewsItem setObject:NewsCurrentElement1 forKey:NewsElement1]; 

     [NewsItem setObject:NewsCurrentElement2 forKey:NewsElement2]; 

     if(NewsNumElements == 3) 
     { 
      [NewsItem setObject:NewsCurrentElement3 forKey:NewsElement3]; 
     } 

     [newsCategories addObject:[[NewsItem copy] autorelease]]; 

     [NewsCurrentElement release]; 
     [NewsCurrentElement1 release]; 
     [NewsCurrentElement2 release]; 

     if(NewsNumElements == 3) 
     { 
      [NewsCurrentElement3 release]; 
     } 

     [NewsItem release]; 

    } 

} 

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

    //NSLog(@"found characters: %@", string); 
    // save the characters for the current item... 
    if ([NewsCurrentElement isEqualToString:NewsElement1]) { 
     [NewsCurrentElement1 appendString:string]; 
    } else if ([NewsCurrentElement isEqualToString:NewsElement2]) { 
     [NewsCurrentElement2 appendString:string]; 
    } else if (NewsNumElements == 3 && [NewsCurrentElement isEqualToString:NewsElement3]) 
    { 
     [NewsCurrentElement3 appendString:string]; 
    } 

} 

- (void)dealloc { 
    [super dealloc]; 

    [newsCategories release]; 
    [NewsItemType release]; 
    [NewsElement1 release]; 
    [NewsElement2 release]; 
    [NewsElement3 release]; 

} 

내가 클래스의 인스턴스를 만들 때 내가 너무 좋아한다 :

 
    NewsFeedParser *categoriesParser = [[NewsFeedParser alloc] init]; 

    if(newsCat == 0) 
    { 
     categoriesParser.NewsItemType = @"article"; 
     categoriesParser.NewsElement1 = @"category"; 
     categoriesParser.NewsElement2 = @"catid"; 
    } 
    else 
    { 
     categoriesParser.NewsItemType = @"article"; 
     categoriesParser.NewsElement1 = @"category"; 
     categoriesParser.NewsElement2 = @"feedUrl"; 
    } 


    [categoriesParser parseXMLFileAtURL:feedUrl]; 
    newsCategories = [[NSMutableArray alloc] initWithArray:categoriesParser.newsCategories copyItems:YES]; 
    [self.tableView reloadData]; 
    [categoriesParser release]; 

하는 경우 누출 도구로 앱을 실행하면 누수가 NewsFeedParser.m의 [NSXMLNewsParser parse] 호출을 가리 킵니다.

http://img139.imageshack.us/img139/3997/leaks.png

이 누수가 어디에서 오는지 내가 알아낼 수 없습니다 내 인생 : 여기

는 NSCFStrings 누출로 누출 기기의 스크린 샷이다. 어떤 도움이라도 대단히 감사하겠습니다.

답변

0

didStartElement 메서드에서 누수가 발생했습니다. elementName을 복사하지 않고 복사하고있었습니다.

 
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{    

    NewsCurrentElement = [[elementName copy] autorelease]; 
    if ([elementName isEqualToString:NewsItemType]) 
    { 
     // clear out our story item caches... 
     NewsItem = [[NSMutableDictionary alloc] init]; 
     NewsCurrentElement1 = [[NSMutableString alloc] init]; 
     NewsCurrentElement2 = [[NSMutableString alloc] init]; 
     if(NewsNumElements == 3) 
     { 
      NewsCurrentElement3 = [[NSMutableString alloc] init]; 
     } 

    } 

} 
0

는 또한 필요한 경우 할당 된 NSMutableString 속성과 같이 재산에 다른 NSMutableString을 할당하기 전에 해제 할 수 있습니다 :

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { 

    if (NewsCurrentElement) { 
     [NewsCurrentElement release], NewsCurrentElement = nil; 
    } 
    NewsCurrentElement = [[elementName copy] autorelease]; 

    if ([elementName isEqualToString:NewsItemType]) { 
     // clear out our story item caches... 
     if (NewsItem) { 
      [NewsItem release], NewsItem = nil; 
     } 
     NewsItem = [[NSMutableDictionary alloc] init]; 

     if (NewsCurrentElement1) { 
      [NewsCurrentElement1 release], NewsCurrentElement1 = nil; 
     } 
     NewsCurrentElement1 = [[NSMutableString alloc] init]; 

     if (NewsCurrentElement2) { 
      [NewsCurrentElement2 release], NewsCurrentElement2 = nil; 
     } 
     NewsCurrentElement2 = [[NSMutableString alloc] init]; 

     if(NewsNumElements == 3) { 
      if (NewsCurrentElement3) { 
       [NewsCurrentElement3 release], NewsCurrentElement3 = nil; 
      } 
      NewsCurrentElement3 = [[NSMutableString alloc] init]; 
     } 
    } 
}