views:

254

answers:

1

Hi everyone

I am building an application that has to handle the parsing of several different kinds of XML files. As I want to standardize the procedure as much as possible, I created a singleton class which handles the parsing of any XML data. The class is handed two options, a unique identifier telling it what kind of XML data it is going to parse and the data itself. Within the class, there is the following function which does the parsing and returns an NSMutableArray object containing the results:

- (NSMutableArray*) initAPIDataParse:(NSData *)data APIRequestType:(int)requestType {

    // Init parser
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];

    // Set delegate for parser
    if (requestType == kXMLParserTypeOne) {
        [parser setDelegate:[[[XMLParserOne alloc] init] autorelease]];
    } else if (requestType == kXMLParserTypeTwo) {
        [parser setDelegate:[[[XMLParserTwo alloc] init] autorelease]];
    } // etc.

    // let's parse the XML
    [parser parse];

    [parser release];

    return lastParsedDict; //lastParsedDict is the NSMutableArray object returned from the Parser delegate
}

Above code works like a charm, except that if you parse the same type of XML multiple times this line leaks (which makes sense):

[parser setDelegate:[[[XMLParserOne alloc] init] autorelease]];

I have tried several things to resolve this issue like creating an instance variable with an instance of the delegate and releasing it whenever the same type of XML Parser was asked for again, yet it didn't work.

I am glad for any help here, thanks a lot!

+1  A: 

Delegates objects are never retained. So using an auto-released object for them is mostl likely going to end up in a crash.

I refactored your code:

- (NSMutableArray*) parseData: (NSData*) data withAPIRequestType: (int) requestType
{
    NSMutableArray* result = nil;

    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
    if (parser != nil)
    {
        switch (requestType) {
            case kXMLParserTypeOne:
                delegate = [XMLParserOne new];
                break;
            case kXMLParserTypeTwo:
                delegate = [XMLParserTwo new];
                break;              
        }

        if (delegate != nil)
        {
            [parser setDelegate: delegate];
            [parser parse];
            result = [delegate.result retain];

            [delegate release];
        }

        [parser release];
    }

    return [result autorelease];
}
St3fan