2010-04-17 1 views
1

&이 NSXMLParser를 사용하는 사용자 정의 클래스를 사용하여 XML 파일을 구문 분석하고 있습니다. 첫 번째 호출에서는 모든 것이 정상이지만 두 번째, 세 번째 이후 호출에서는 didEndElement, didEndElement 및 foundCharacters 함수 내부의 특정 줄에서 수십 개의 메모리 누수가 표시됩니다. 나는 이걸 챙겨서이 문제가있는 사람들을 찾았지만, 정말로 도움이 될만한 것을 찾지 못했습니다.NSXMLParser 및 메모리 누수

내 파서 클래스는 다음과 같습니다

Parser.h

@interface XMLParser : NSObject { 
NSMutableArray *data; 
NSMutableString *currentValue; 
NSArray *xml; 
NSMutableArray *videos; 
NSMutableArray *photos; 
NSXMLParser *parser; 
NSURLConnection *feedConnection; 
NSMutableData *downloadedData; 

Content *content; 
Video *video; 

BOOL nowPhoto; 
BOOL nowVideo; 
    BOOL finished; 
    BOOL webTV; 
} 


-(void)parseXML:(NSURL*)xmlURL; 
-(int)getCount; 
-(NSArray*)getData; 
//- (void)handleError:(NSError *)error; 

//@property(nonatomic, retain) NSMutableString *currentValue; 
@property(nonatomic, retain) NSURLConnection *feedConnection; 
@property(nonatomic, retain) NSMutableData *downloadedData; 
@property(nonatomic, retain) NSArray *xml; 
@property(nonatomic, retain) NSXMLParser *parser; 
@property(nonatomic, retain) NSMutableArray *data; 
@property(nonatomic, retain) NSMutableArray *photos; 
@property(nonatomic, retain) NSMutableArray *videos; 
@property(nonatomic, retain) Content *content; 
@property(nonatomic, retain) Video *video; 

@property(nonatomic) BOOL finished; 
@property(nonatomic) BOOL nowPhoto; 
@property(nonatomic) BOOL nowVideo; 
@property(nonatomic) BOOL webTV; 
@end 

에게 Parser.m

어딘가에
#import "Content.h" 
#import "Video.h" 
#import "Parser.h" 
#import <CFNetwork/CFNetwork.h> 

@implementation XMLParser 

@synthesize xml, parser, finished, nowPhoto, nowVideo, webTV; 
@synthesize feedConnection, downloadedData, data, content, photos, videos, video; 

-(void)parseXML:(NSURL*)xmlURL { 

    /* 
    NSURLRequest *req = [NSURLRequest requestWithURL:xmlURL]; 
    self.feedConnection = [[[NSURLConnection alloc] initWithRequest:req delegate:self] autorelease]; 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 
    */ 

    [[NSURLCache sharedURLCache] setMemoryCapacity:0]; 
    [[NSURLCache sharedURLCache] setDiskCapacity:0]; 


    NSXMLParser *feedParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL]; 
    //NSXMLParser *feedParser = [[NSXMLParser alloc] initWithData:theXML]; 
    [self setParser:feedParser]; 
    [feedParser release]; 

    [[self parser] setDelegate:self]; 
    [[self parser] setShouldResolveExternalEntities:YES]; 
    [[self parser] parse]; 

} 


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

    if ([elementName isEqualToString:@"articles"]) { 
     self.finished = NO; 
     self.nowPhoto = NO; 
     self.nowVideo = NO; 
     self.webTV = NO; 

     if (!data) { 
      NSMutableArray *tmp = [[NSMutableArray alloc] init]; 
      [self setData:tmp]; 
      [tmp release]; 
      return ; 
     } 
    } 

    if ([elementName isEqualToString:@"WebTV"]) { 
     self.finished = NO; 
     self.nowPhoto = NO; 
     self.nowVideo = NO; 
     self.webTV = YES; 

     if (!data) { 
      NSMutableArray *tmp = [[NSMutableArray alloc] init]; 
      [self setData:tmp]; 
      [tmp release]; 
      return ; 
     } 
    } 


    if ([elementName isEqualToString:@"photos"]) { 
     if (!photos) { 
      NSMutableArray *tmp = [[NSMutableArray alloc] init]; 
      [self setPhotos:tmp]; 
      [tmp release]; 
      return; 
     } 
    } 

    if ([elementName isEqualToString:@"videos"]) { 
     if (!videos) { 
      NSMutableArray *tmp = [[NSMutableArray alloc] init]; 
      [self setVideos:tmp]; 
      [tmp release]; 
      return; 
     } 
    } 


    if ([elementName isEqualToString:@"photo"]) { 
     self.nowPhoto = YES; 
     self.nowVideo = NO; 
    } 

    if ([elementName isEqualToString:@"video"]) { 
     self.nowPhoto = NO; 
     self.nowVideo = YES; 
    } 

    if ([elementName isEqualToString:@"WebTVItem"]) { 
     if (!video) { 
      Video *tmp = [[Video alloc] init]; 
      [self setVideo:tmp]; 
      [tmp release]; 
     } 

     NSString *videoId = [attributeDict objectForKey:@"id"]; 
     [[self video] setVideoId:[videoId intValue]]; 

    } 

    if ([elementName isEqualToString:@"article"]) { 
     if (!content) { 
      Content *tmp = [[Content alloc] init]; 
      [self setContent:tmp]; 
      [tmp release]; 
     } 

     NSString *contentId = [attributeDict objectForKey:@"id"]; 
     [[self content] setContentId:[contentId intValue]]; 

     return; 
    } 


    if ([elementName isEqualToString:@"category"]) { 
     NSString *categoryId = [attributeDict objectForKey:@"id"]; 
     NSString *parentId = [attributeDict objectForKey:@"parent"]; 

     [[self content] setCategoryId:[categoryId intValue]]; 
     [[self content] setParentId:[parentId intValue]]; 


     categoryId = nil; 
     parentId = nil; 

     return; 
    } 

    if ([elementName isEqualToString:@"vCategory"]) { 
     NSString *categoryId = [attributeDict objectForKey:@"id"]; 
     NSString *parentId = [attributeDict objectForKey:@"parent"]; 

     [[self video] setCategoryId:[categoryId intValue]]; 
     [[self video] setParentId:[parentId intValue]]; 

     categoryId = nil; 
     parentId = nil; 


     return; 
    } 


} 


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


    if (!currentValue) { 
     currentValue = [[NSMutableString alloc] initWithCapacity:1000]; 
    } 


    if (currentValue != @"\n") 
    [currentValue appendString:string];    
} 




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

    NSString *cleanValue = [currentValue stringByReplacingOccurrencesOfString:@"\n" withString:@""] ; 

    if ([elementName isEqualToString:@"articles"]) { 
     self.finished = YES; 

     //[content release]; 
    } 

    if ([elementName isEqualToString:@"article"]) { 
     [[self data] addObject:[self content]]; 
     [self setContent:nil]; 
     [self setPhotos:nil]; 
     [self setVideos:nil]; 

     /* 
     [content release]; 
     content = nil; 

     [videos release]; 
     videos = nil; 

     [photos release]; 
     photos = nil; 
     */ 
    } 

    if ([elementName isEqualToString:@"WebTVItem"]) { 
     [[self data] addObject:[self video]]; 
     [self setVideo:nil]; 

     //[video release]; 
     //video = nil; 
    } 

    if ([elementName isEqualToString:@"title"]) { 
     //NSLog(@"Tit: %@",cleanValue); 
     [[self content] setTitle:cleanValue]; 
    } 

    if ([elementName isEqualToString:@"vTitle"]) { 
     [[self video] setTitle:cleanValue]; 
    } 

    if ([elementName isEqualToString:@"link"]) { 
     //NSURL *url = [[NSURL alloc] initWithString:cleanValue] ; 
     [[self content] setUrl:[NSURL URLWithString:cleanValue]]; 
     [[self content] setLink: cleanValue]; 

     //[url release]; 
     //url = nil; 
    } 

    if ([elementName isEqualToString:@"vLink"]) { 
     [[self video] setLink:cleanValue]; 
     [[self video] setUrl:[NSURL URLWithString:cleanValue]]; 
    } 


    if ([elementName isEqualToString:@"teaser"]) { 
     NSString *tmp = [cleanValue stringByReplacingOccurrencesOfString:@"##BREAK##" withString:@"\n"]; 
     [[self content] setTeaser:tmp]; 
     tmp = nil; 
    } 

    if ([elementName isEqualToString:@"content"]) { 
     NSString *tmp = [cleanValue stringByReplacingOccurrencesOfString:@"##BREAK##" withString:@"\n"]; 
     [[self content] setContent:tmp]; 

     tmp = nil; 
    } 

    if ([elementName isEqualToString:@"category"]) { 
     [[self content] setCategory:cleanValue]; 
    } 

    if ([elementName isEqualToString:@"vCategory"]) { 
     [[self video] setCategory:cleanValue]; 
    } 


    if ([elementName isEqualToString:@"date"]) { 
     [[self content] setDate:cleanValue]; 
    } 

    if ([elementName isEqualToString:@"vDate"]) { 
     [[self video] setDate:cleanValue]; 
    } 

    if ([elementName isEqualToString:@"thumbnail"]) { 
     [[self content] setThumbnail:[NSURL URLWithString:cleanValue]]; 

     [[self content] setThumbnailURL:cleanValue]; 
    } 

    if ([elementName isEqualToString:@"vThumbnail"]) { 
     [[self video] setThumbnailURL:cleanValue]; 
     [[self video] setThumbnail:[NSURL URLWithString:cleanValue]]; 
    } 

    if ([elementName isEqualToString:@"vDirectLink"]){ 
     [[self video] setDirectLink: cleanValue]; 
    } 

    if ([elementName isEqualToString:@"preview"]){ 
     [[self video] setPreview: cleanValue]; 
    } 

    if ([elementName isEqualToString:@"thumbnail_position"]){ 
     [[self content] setThumbnailPosition: cleanValue]; 
    } 


    if ([elementName isEqualToString:@"url"]) { 
     if (self.nowPhoto == YES) { 
      [[self photos] addObject:cleanValue]; 
     } 
     else if (self.nowVideo == YES) { 
      [[self videos] addObject:cleanValue]; 
     } 
    } 


    if ([elementName isEqualToString:@"photos"]) { 

     [[self content] setPhotos:[self photos]]; 
     //[photos release]; 
     //photos = nil; 

     self.nowPhoto = NO; 
    } 


    if ([elementName isEqualToString:@"videos"]) { 
     [[self content] setVideos:[self videos]]; 
     //[videos release]; 
     //videos = nil; 

     self.nowVideo = NO; 
    } 

    //[cleanValue release]; 
    //cleanValue = nil; 

    [currentValue release]; 
    currentValue = nil; 

} 

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError { 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"Error" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
    [alert show]; 
    [alert release]; 
} 

-(NSArray*)getData { 


    return data; 
} 


-(int)getCount { 
    return [data count]; 
} 

- (void)dealloc { 
    [parser release]; 
    //[data release]; 
    //[photos release]; 
    //[videos release]; 
    //[video release]; 
    //[content release]; 
    [currentValue release]; 

    [super dealloc]; 
} 


@end 

을 내 코드에서,이 클래스의 인스턴스를 생성 :

XMLParser* feed = [[XMLParser alloc] init]; 
[self setRssParser:feed]; 
[feed release]; 

// Parse feed 
NSString *url = [NSString stringWithFormat:@"MyXMLURL"]; 
[[self rssParser] parseXML:[NSURL URLWithString:url]]; 

이제 문제는 첫 번째 (누수가없는) 이후에는 악기가이 부분과 같이 너무 많은 부분에 누출을 표시한다는 것입니다 (모든 항목을 열거하기에는 너무 많지만 모든 호출이 동일하게 보이기 때문에 누출 선을 굵게 표시했습니다) :

didEndElement에서

이 pealse를 해결하는 방법

if ([elementName isEqualToString:@"link"]) { 
    // THIS LINE IS LEAKING => INSTRUMENTS SAYS IT IS A NSCFString LEAK 
    [self content] setUrl:[NSURL URLWithString:cleanValue]]; 
    [[self content] setLink: cleanValue]; 

} 

어떤 생각? (NSXMLParser Leaking

답변

0
-(BOOL)fetchAndParseRss{ 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

[UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 

//To suppress the leak in NSXMLParser 
[[NSURLCache sharedURLCache] setMemoryCapacity:0]; 
[[NSURLCache sharedURLCache] setDiskCapacity:0]; 

NSURL *url = [NSURL URLWithString:GALLERY_FEED]; 
BOOL success = NO; 
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url]; 
[parser setDelegate:self]; 
[parser setShouldProcessNamespaces:YES]; 
[parser setShouldReportNamespacePrefixes:YES]; 
[parser setShouldResolveExternalEntities:NO]; 
success = [parser parse]; 
[parser release]; 
[pool drain]; 
return success; 
} 
+1

나를 위해 일한 .......... – sambasivarao4u

0

this 페이지에서 볼 때, 당신은뿐만 아니라 누수를 제거하기 위해 다음을 수행 할 수 있습니다 이 여기 리 Amtrong에 의해 (사과 버그 등) 언급 한 것과 같은 문제가 될 수 setMemoryCapacity 또는 setDiskCapacity 호출이 필요 없음을 알았습니다.) :

NSData *xml = [NSData 
     dataWithContentsOfURL: [NSURL 
     URLWithString:@"http://some-xml-url.com/my.xml"]]; 

NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xml];