【问题标题】:NSXMLParser & memory leaksNSXMLParser & 内存泄漏
【发布时间】:2011-02-09 03:08:21
【问题描述】:

我正在使用实例化和使用 NSXMLParser 的自定义类来解析 XML 文件。在第一次调用时一切都很好,但在第二次、第三次和以后的调用中,仪器在 didEndElement、didEndElement 和 foundCharacters 函数的某些行上显示了数十个内存泄漏。 我用谷歌搜索了它,发现有些人遇到了这个问题,但我没有找到任何可以真正帮助我的东西。

我的 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

解析器.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];

}

知道如何解决这个问题吗? 这是否与 Lee Amtron 在这里提到的问题(作为苹果虫)相同:NSXMLParser Leaking

【问题讨论】:

    标签: iphone memory-leaks nsxmlparser


    【解决方案1】:

    正如在this 页面上发现的那样,您也可以执行以下操作来消除泄漏(我发现您不需要 setMemoryCapacity 或 setDiskCapacity 调用):

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

    【讨论】:

      【解决方案2】:
      -(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;
      }
      

      【讨论】:

        猜你喜欢
        • 2016-05-09
        • 2011-02-21
        • 1970-01-01
        • 2012-02-12
        • 1970-01-01
        • 1970-01-01
        • 2010-12-24
        • 2011-07-03
        • 1970-01-01
        相关资源
        最近更新 更多