NSXMLParser Утечки большое время!Какие-либо предложения? - PullRequest
1 голос
/ 20 января 2011


Я пишу приложение, которое использует NSXMLParser - и это убивает меня.
Изначально я заставлял парсер загружать фид из Интернета, и он пропускал много памяти, а теперь я где-то читал, что лучше использовать NSURLConnection для загрузки данных, а затем передавать их парсеру. Проблема в том, что у меня все еще есть проблемы с памятью.
У кого-нибудь есть какие-либо советы о том, как заставить эту вещь работать без утечек?

Большое спасибо!

Общая идея такова. Класс RSSParser, вызывается из контроллера CategoriesControl в viewDidLoad. Швы утечки будут происходить в RSSParser, а именно эти строки:

[parser parse] или [parsedItems addObject: [parsedItem copy]];

И утечки появляются, когда я отхожу от контроллера категорий.

//RSSParser.h

#import 
#import "Subscriptions.h"
@interface RSSParser : NSObject  {
    NSMutableArray          *parsedItems;
    NSMutableDictionary     *parsedItem;
    NSXMLParser     *parser;    
    NSString    *item;
    NSString    *ititle;
    NSString    *link;
    NSString    *description;
    NSString    *guid;
    NSString    *pubDate;
}
@property (nonatomic, retain) NSMutableArray *parsedItems;
@property (nonatomic, retain) NSXMLParser *parser;
- (void)fetch:(NSMutableData *)dt;
@end
//RSSParser.m

#import "RSSParser.h"

@implementation RSSParser

@synthesize parser, parsedItems;

- (void)fetch:(NSMutableData *)dt {
    parsedItems = [[NSMutableArray alloc] init];
    parser = [[NSXMLParser alloc] initWithData:dt];
    [parser setDelegate:self];
    [parser setShouldProcessNamespaces:NO]; 
    [parser setShouldReportNamespacePrefixes:NO]; 
    [parser setShouldResolveExternalEntities:NO]; 
    [parser parse]; 
    [parser release];
}

- (void)parserDidStartDocument:(NSXMLParser *)parser {
} 

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError { 
    UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:@"Probleme me te dhenat." message:@"Ju lutem provoni te rilidheni me vone." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
    [errorAlert show]; 
    [errorAlert release];
} 

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{  
    item = [[elementName copy] autorelease]; 
    if ([elementName isEqualToString:@"item"]) { 
        parsedItem  = [[[NSMutableDictionary    alloc] init] autorelease]; 
        ititle      = [[[NSMutableString        alloc] init] autorelease]; 
        link        = [[[NSMutableString        alloc] init] autorelease]; 
        description = [[[NSMutableString        alloc] init] autorelease]; 
        guid        = [[[NSMutableString        alloc] init] autorelease]; 
        pubDate     = [[[NSMutableString        alloc] init] autorelease]; 
    } 
} 

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ 
    if ([item isEqualToString:@"title"]) { 
        ititle = [ititle stringByAppendingString:string];
    } else if ([item isEqualToString:@"link"]) { 
        link = [link stringByAppendingString:string];
    } else if ([item isEqualToString:@"description"]) { 
        description = [description stringByAppendingString:string];
    } else if ([item isEqualToString:@"guid"]) { 
        guid = [guid stringByAppendingString:string];
    } else if ([item isEqualToString:@"pubDate"]) { 
        pubDate = [pubDate stringByAppendingString:string];
    }
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{ 
    if ([elementName isEqualToString:@"item"]) { 
        if (![ititle isEqualToString:@""])      { [parsedItem setObject:ititle forKey:@"title"]; }
        if (![link isEqualToString:@""])        { [parsedItem setObject:link forKey:@"link"]; }
        if (![description isEqualToString:@""]) { [parsedItem setObject:description forKey:@"description"]; }
        if (![guid isEqualToString:@""])        { [parsedItem setObject:guid forKey:@"guid"]; }
        if (![pubDate isEqualToString:@""])     { [parsedItem setObject:pubDate forKey:@"pubDate"]; }
        [parsedItems addObject:[parsedItem copy]]; 
    } 
}

- (void)parserDidEndDocument:(NSXMLParser *)parser {
}

@end


*****************************************
//CategoriesController.m

- (void)viewDidLoad {
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.ikub.al/RssCategory.aspx?catId=%@", address]]];
    connection = [NSURLConnection connectionWithRequest:request delegate:self];
    if (connection) {
        downloadedData = [[NSMutableData data] retain];
    } else {
        NSLog(@"Cannot get the data stream.");
    }

    if ([address length] > 0) {
        UIBarButtonItem *subscribeButton = [[UIBarButtonItem alloc] initWithTitle:@"Abonohu" style:UIBarButtonItemStyleBordered target:self action:@selector(newSubscription)];
        self.navigationItem.rightBarButtonItem = subscribeButton;
        [subscribeButton release];
    }   
    [super viewDidLoad];
}

- (void)connection:(NSURLConnection *)theConnection didReceiveResponse:(NSURLResponse *)response {
    [downloadedData setLength:0];
}  

- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)data {
    [downloadedData appendData:data];

}

- (void)connection:(NSURLConnection *)theConnection didFailWithError:(NSError *)error {
    UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:@"Probleme me lidhjen." message:@"Ju lutemi te kontrolloni lidhjen tuaj WiFi, GPRS/EDGE/3G." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
    [errorAlert show]; 
    [errorAlert release];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)theConnection {
    parser = [[RSSParser alloc] init];
    [parser fetch:downloadedData];
    parsedItems = [parser.parsedItems copy];
    [parser.parsedItems release];
    [categoriesTable reloadData];
    [parser release];
}
...