Iphone NSXMLParser&内存泄漏

Iphone NSXMLParser&内存泄漏,iphone,memory-leaks,nsxmlparser,Iphone,Memory Leaks,Nsxmlparser,我正在使用实例化并使用NSXMLParser的自定义类解析XML文件。在第一次调用中,一切正常,但在第二次、第三次和以后的调用中,仪器显示在DiEndElement、DiEndElement和foundCharacters函数中的某些行上存在数十个内存泄漏。 我在谷歌上搜索了一下,发现有些人有这个问题,但我没有找到任何能真正帮助我的东西 我的解析器类如下所示: 解析器.h @interface XMLParser : NSObject { NSMutableArray *data; NSMut

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

我的解析器类如下所示:

解析器.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
现在的问题是,在第一个零泄漏后,仪器显示了太多的泄漏部分,比如这一个,它们太多,无法全部列举,但所有调用看起来都一样,我将泄漏线改为粗体:

在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吗? 这是否与Lee Amtrong在此处提到的苹果漏洞问题相同:

如第页所示,您也可以执行以下操作来消除泄漏。我发现您不需要setMemoryCapacity或setDiskCapacity调用:

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

NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xml];
-(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;
}
NSData *xml = [NSData
        dataWithContentsOfURL: [NSURL
        URLWithString:@"http://some-xml-url.com/my.xml"]];

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