Memory Leak Using NSXMLParser in NSConcreteMapTable

核能气质少年 提交于 2020-02-02 06:25:05

问题


I'm using NSXMLParser and I get a memory leak that points to NSConcreteMapTable, whatever that is:

The leak occurs at this line of code when calling the parser from my AppDelegate.m:

I have searched for a solution and can't see what I'm doing wrong. Here is my code. Any help is greatly appreciated. lq

// * * * XMLParser.h * * *  

#import <Foundation/Foundation.h>

@protocol NSXMLParserDelegate;

@interface XMLParser : NSObject 
<NSXMLParserDelegate>
{
    NSMutableArray  *xmlArray;
    BOOL        storingCharacters;
    float       xmlDataVersion;
}

@property (nonatomic, retain) NSMutableArray *xmlArray;
@property (nonatomic)  BOOL storingCharacters;
@property (nonatomic, assign) float xmlDataVersion;

-(BOOL)parseXMLFileAtURL:(NSURL *)URL parseError:(NSError **)error;

@end

// * * * XMLParser.m * * *

#import "XMLParser.h"

@implementation XMLParser

@synthesize xmlArray;
@synthesize storingCharacters;
@synthesize xmlDataVersion;

- (BOOL)parseXMLFileAtURL:(NSURL *)URL parseError:(NSError **)error {

    BOOL result = YES;

    if (xmlArray == nil) {  
        // this array holds row data extracted from the XML parser didStartElement method                                           
        xmlArray = [[NSMutableArray alloc] init];
    }

    [[NSURLCache sharedURLCache] setMemoryCapacity:0];
    [[NSURLCache sharedURLCache] setDiskCapacity:0];
    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];

    if (parser != nil) {
        [parser setDelegate:self];
        [parser setShouldProcessNamespaces:NO];
        [parser setShouldReportNamespacePrefixes:NO];
        [[parser setShouldResolveExternalEntities:NO];
    }

    [parser parse];

    if (parseError && error) {
        *error = parseError;
        result = NO;
    }

    [parser release];
    return result;

}

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

    if (qName) {
        elementName = qName;
    }

    // Check the data version of the XML Data against my stored value

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

        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
        self.xmlDataVersion = [[attributeDict objectForKey:@"version"] floatValue];
        float storedDataVersion = [userDefaults floatForKey:kDataVersion];

       if (self.xmlDataVersion <= storedDataVersion) {
           // - - - - -> Abort parsing if the same or earlier data versions
           [parser abortParsing];
       }

    }

    if ([elementName isEqualToString:@"FirstColumnName"]) {
        storingCharacters = YES;
    } else if ([elementName isEqualToString:@"SecondColumnName"]) {
        storingCharacters = YES;
        // ... total of 16 elements
    }

}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    if (storingCharacters) {        
        [self.xmlArray addObject:string];
    }
}

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

    if (qName) {
        elementName = qName;
    }

    // - - - - -> If at the end of a data row, save changes to object model

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

        // - - - - -> Make sure the data has the required number of elements before taking any action

        if ([self.xmlArray count] == 16) {

            // … //Store or Update Data in SQLite store depending on data values    

        }

        [self.xmlArray removeAllObjects];   

    }

    storingCharacters = NO;
}

-(void)dealloc {
    [xmlArray release];
    [super dealloc];
}


// * * * AppDelegate.m * * *

#import "XMLParser.h"

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(UIApplication *)application { 

    NSURL *xmlURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"FileName" ofType:@"xml"]];

    NSError *parseError = nil;

    XMLParser *xmlParse = [[XMLParser alloc] init];
    [xmlParse parseXMLFileAtURL:xmlURL parseError:&parseError];
    [xmlParse release];

    . . .

}


回答1:


I found a solution in another SO post:

Use:

NSData * dataXml = [[NSData alloc] initWithContentsOfURL:URL];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:dataXml];
[dataXml release];

Instead of:

NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];

The leak goes away.




回答2:


This is probably a leak in Apple code, since Foundation is reported as "Responsible Library". There's probably nothing you can do, but to report the bug to apple.



来源:https://stackoverflow.com/questions/6019240/memory-leak-using-nsxmlparser-in-nsconcretemaptable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!