2010-04-17 100 views
1

我正在使用自定义类来解析XML文件,该类定制了&使用NSXMLParser。在第一次调用时,一切正常,但在第二次,第三次和以后的调用中,Instruments在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:

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

} 

任何想法如何解决这一问题pealse? 难道这是同样的问题提到的(如苹果的bug)李Amtrong这里: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 2011-01-18 12:42:21

0

this页找到,你可以做以下摆脱泄漏以及(我发现你不需要setMemoryCapacity或setDiskCapacity调用):

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

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